<!doctype html>
<html lang="zh-Hans-CN">
<head>
<meta charset="utf-8" />
<title>Minecraft 原版模组入门教程</title>
<meta name='author' content='ruhuasiyu@mcbbs' />
<meta name='keywords' content='minecraft, 原版模组, vanilla mod, datapacks' />
<meta name='description' content='Minecraft 原版模组入门教程' />
<meta name='revised' content='ruhuasiyu@mcbbs' />
<base href="" />
<link rel="shortcut icon" href="https://zhangshenxing.gitee.io/favicon.ico" />
<link rel="stylesheet" href="items/style.css" />
<script>
  function hidecomment(thiselement){
    var classElements = document.getElementsByClassName('comment');
    for (var i=0; i<classElements.length; i++) {
      classElements[i].style.display = 'none';
    }
    thiselement.style.display='none';
    thiselement.nextElementSibling.style.display='block';
  }
  function showcomment(thiselement){
    var classElements = document.getElementsByClassName('comment');
    for (var i=0; i<classElements.length; i++) {
      classElements[i].style.display = 'inline';
    }
    thiselement.previousElementSibling.style.display='block';
    thiselement.style.display='none';        
  }
  function content_level_1(thiselement){
    var i;
    var navall = document.getElementsByTagName('nav')[0].childNodes[1].getElementsByTagName('li');
    for (i=0; i<navall.length; i++) navall[i].style.display = 'none';
    var navsec = document.getElementsByTagName('nav')[0].childNodes[1].childNodes;
    for (i=1; i<navsec.length; i+=2) navsec[i].style.display = 'block';
    thiselement.style.display='none';
    thiselement.nextElementSibling.style.display='block';
  }
  function content_level_2(thiselement){
    var i,j;
    var navall = document.getElementsByTagName('nav')[0].childNodes[1].getElementsByTagName('li');
    for (i=0; i<navall.length; i++) {
      navall[i].style.display = 'none';
    }
    var navsec = document.getElementsByTagName('nav')[0].childNodes[1].childNodes;
    var navsubsec;

    navsec[1].style.display = 'block';
    navsec[3].style.display = 'block';
    navsubsec = navsec[3].childNodes[2].childNodes;
    for (j=1; j<navsubsec.length; j+=2) navsubsec[j].style.display = 'block';

    for (i=5; i<navsec.length; i+=2) {
      navsec[i].style.display = 'block';
      if(navsec[i].childNodes.length>=2){
        navsubsec = navsec[i].childNodes[1].childNodes;
        for (j=1; j<navsubsec.length; j+=2) navsubsec[j].style.display = 'block';
      }
    }
    thiselement.style.display='none';
    thiselement.nextElementSibling.style.display='block';
  }
  function content_level_3(thiselement){
    var i;
    var navall = document.getElementsByTagName('nav')[0].childNodes[1].getElementsByTagName('li');
    for (i=0; i<navall.length; i++) navall[i].style.display = 'block';
    thiselement.style.display='none';
    thiselement.previousElementSibling.previousElementSibling.style.display='block';
  }
  function loadpage(){
    var files=document.getElementsByClassName("file");
    for (var i=0;i<files.length;i++) {
      files[i].onclick=function (){
        var j=1;
        if (this.nextElementSibling.style.display=='none') j=0;
        if (j==1) this.nextElementSibling.style.display='none';
        else this.nextElementSibling.style.display='block';
      }
    }
  }
</script>
<!-- <style>
  html{  
    filter: grayscale(100%);  
    -webkit-filter: grayscale(100%);  
    -moz-filter: grayscale(100%);  
    -ms-filter: grayscale(100%);  
    -o-filter: grayscale(100%);
  }
</style> -->
</head>
<body onload="loadpage();">
<nav>
<ul>
  <li><a href="#引言" style="font-weight: bold; text-align: center;">理论篇</a></li>
  <li>
    <a href="#引言">§1. 引言</a><ul>
    <li><a href="#命令基础">§1.1. 命令基础</a></li>
    <li><a href="#工具准备">§1.2. 工具准备</a><ul>
      <li><a href="#文本编辑器">§1.2.1. 文本编辑器</a></li>
      <li><a href="#压缩软件">§1.2.2. 压缩软件</a></li>
      <li><a href="#NBT_编辑器">§1.2.3. NBT 编辑器</a></li>
      <li><a href="#绘图工具">§1.2.4. 绘图工具</a></li>
    </ul></li>
    <li><a href="#文件结构">§1.3. 游戏文件夹</a></li>
    <li><a href="#JSON文件">§1.4. JSON文件</a></li>
  </ul></li>
  <li><a href="#数据包">§2 数据包</a><ul>
    <li><a href="#数据包/元信息和图标">§2.1 元信息和图标</a></li>
    <li><a href="#数据包/命名空间">§2.2 命名空间</a></li>
    <li><a href="#函数">§2.3 函数</a></li>
    <li><a href="#进度">§2.4 进度</a></li>
    <li><a href="#战利品表">§2.5 战利品表</a></li>
    <li><a href="#战利品表谓词">§2.6 战利品表谓词</a></li>
    <li><a href="#物品修饰器">§2.7 物品修饰器</a></li>
    <li><a href="#配方">§2.8 配方</a><ul>
      <li><a href="#有序合成">§2.8.1 有序合成</a></li>
      <li><a href="#无序合成">§2.8.2 无序合成</a></li>
      <li><a href="#切石机配方">§2.8.3 切石机配方</a></li>
      <li><a href="#烧炼配方">§2.8.4 烧炼配方</a></li>
      <li><a href="#锻造台配方">§2.8.5 锻造台配方</a></li>
      <li><a href="#工作台特殊配方">§2.8.6 工作台特殊配方</a></li>
      <li><a href="#覆盖原版配方">§2.8.7 覆盖原版配方</a></li>
      <li><a href="#配方获取">§2.8.8 配方获取</a></li>
    </ul></li>
    <li><a href="#结构">§2.9 结构</a></li>
    <li><a href="#标签">§2.10 标签</a><ul>
      <li><a href="#方块标签">§2.10.1 方块标签</a></li>
      <li><a href="#物品标签">§2.10.2 物品标签</a></li>
      <li><a href="#函数标签">§2.10.3 函数标签</a></li>
      <li><a href="#实体类型标签">§2.10.4 实体类型标签</a></li>
      <li><a href="#流体标签">§2.10.5 流体标签</a></li>
      <li><a href="#游戏事件标签">§2.10.6 游戏事件标签</a></li>
    </ul></li>
    <li><a href="#维度和维度类型">§2.11 维度和维度类型</a><ul>
      <li><a href="#维度">§2.11.1 维度</a></li>
      <li><a href="#维度类型">§2.11.2 维度类型</a></li>
      <li><a href="#维度实例">§2.11.3 实例</a></li>
      <li><a href="#自定义世界">§2.11.4 自定义世界</a></li>
    </ul></li>
    <li><a href="#自定义世界生成">§2.12 自定义世界生成</a><ul>
      <li><a href="#噪声设置">§2.12.1 噪声设置</a></li>
      <li><a href="#生物群系">§2.12.2 生物群系</a></li>
      <li><a href="#地形雕刻器">§2.12.3 地形雕刻器</a></li>
      <li><a href="#地表生成器">§2.12.4 地表生成器</a></li>
      <li><a href="#地物">§2.12.5 地物</a><ul>
        <li><a href="#地物/JSON格式">JSON格式</a></li>
        <li><a href="#可用的地物">可用的地物</a></li>
        <li><a href="#装饰物">装饰物</a></li>
        <li><a href="#可用的装饰物">可用的装饰物</a></li>
      </ul></li>
      <li><a href="#结构地物">§2.12.6 结构地物</a><ul>
        <li><a href="#结构地物/JSON格式">JSON格式</a></li>
        <li><a href="#可用的结构地物">可用的结构地物</a></li>
      </ul></li>
      <li><a href="#模板池">§2.12.8 模板池</a></li>
      <li><a href="#处理器列表">§2.12.9 处理器列表</a><ul>
        <li><a href="#处理器列表/JSON格式">JSON格式</a></li>
        <li><a href="#可用的处理器列表">可用的处理器列表</a></li>
      </ul></li>
    </ul></li>
  </ul></li>
  <li><a href="#资源包">§3 资源包</a><ul>
    <li><a href="#资源包/元信息和图标">§3.1 元信息和图标</a></li>
    <li><a href="#资源包/命名空间">§3.2 命名空间</a></li>
    <li><a href="#语言文件">§3.3 语言文件</a></li>
    <li><a href="#自定义物品模型">§3.4 自定义物品模型</a></li>
    <li><a href="#模型">§3.5 模型</a></li>
    <li><a href="#纹理">§3.6 纹理</a></li>
    <li><a href="#音效">§3.7 音效</a></li>
    <li><a href="#字体">§3.8 字体</a></li>
    <li><a href="#着色器">§3.9 着色器</a><ul>
      <li><a href="#后处理着色器">§3.9.1 后处理着色器</a></li>
      <li><a href="#核心着色器">§3.9.2 核心着色器</a></li>
    </ul></li>
    <li><a href="#文本">§3.10 文本</a></li>
  </ul></li>
  <li><a href="#规划" style="font-weight: bold; text-align: center;">实践篇</a></li>
  <li><a href="#规划">§4. 规划</a><ul>
    <li><a href="#名称设计">§4.1 名称设计</a></li>
    <li><a href="#调试">§4.2 调试</a></li>
    <li><a href="#前置与附属">§4.3 前置与附属</a></li>
    <li><a href="#发布">§4.4 发布</a></li>
  </ul></li>
  <li><a href="#物品设计">§5 物品设计</a><ul>
    <li><a href="#通用处理">§5.1 通用处理</a></li>
    <li><a href="#右键交互">§5.2 右键交互</a></li>
    <li><a href="#食物">§5.3 食物</a></li>
    <li><a href="#药水">§5.4 药水</a></li>
    <li><a href="#自定义状态效果">§5.5 自定义状态效果</a></li>
    <li><a href="#头饰">§5.6 头饰</a></li>
    <li><a href="#盔甲">§5.7 盔甲</a></li>
    <li><a href="#工具和武器">§5.8 工具和武器</a></li>
    <li><a href="#画">§5.9 画</a></li>
  </ul></li>
  <li><a href="#方块设计">§6 方块设计</a><ul>
    <li><a href="#视线追踪法">§6.1 视线追踪法</a></li>
    <li><a href="#计算交点法">§6.2 计算交点法</a></li>
    <li><a href="#命令方块替换法">§6.3 命令方块替换法</a></li>
    <li><a href="#破坏事件">§6.4 破坏事件</a></li>
    <li><a href="#模型设置">§6.5 模型设置</a></li>
  </ul></li>
  <li><a href="#机器设计">§7 机器设计</a><ul>
    <li><a href="#GUI纹理模型">§7.1 GUI纹理模型</a></li>
    <li><a href="#GUI背景处理">§7.2 GUI背景处理</a></li>
    <li><a href="#GUI命令">§7.3 GUI命令</a></li>
    <li><a href="#物品输出">§7.4 物品输出</a></li>
    <li><a href="#配方处理">§7.5 配方处理</a></li>
    <li><a href="#插件">§7.6 插件</a></li>
    <li><a href="#容器扩展">§7.7 容器扩展</a></li>
    <li><a href="#接口">§7.8 接口</a></li>
    <li><a href="#管道">§7.9 管道</a><ul>
      <li><a href="#无线传输">§7.9.1 无线传输</a></li>
      <li><a href="#管道式">§7.9.2 管道式</a></li>
      <li><a href="#激光式">§7.9.3 激光式</a></li>
      <li><a href="#载体式">§7.9.4 载体式</a></li>
      <li><a href="#管道设计">§7.9.5 管道设计</a></li>
    </ul></li>
  </ul></li>
  <li><a href="#NBT合成与烧炼">§8 NBT合成与烧炼</a><ul>
    <li><a href="#地板合成">§8.1 地板合成</a></li>
    <li><a href="#实体背包合成">§8.2 实体背包合成</a></li>
    <li><a href="#容器合成">§8.3 容器合成</a></li>
    <li><a href="#NBT烧炼">§8.4 NBT烧炼</a><ul>
      <li><a href="#替换产物法">§8.4.1 替换产物法</a></li>
      <li><a href="#记分板模拟">§8.4.2 记分板模拟</a></li>
    </ul></li>
    <li><a href="#NBT酿造">§8.5 NBT酿造</a></li>
  </ul></li>
  <li><a href="#植物">§9 植物</a><ul>
    <li><a href="#作物">§9.1 作物</a></li>
    <li><a href="#花草">§9.2 花草</a></li>
    <li><a href="#树">§9.3 树</a></li>
  </ul></li>
  <li><a href="#物品与实体处理">§10 物品与实体处理</a><ul>
    <li><a href="#修改玩家背包">§10.1 修改玩家背包</a></li>
    <li><a href="#耐久处理">§10.2 耐久处理</a></li>
    <li><a href="#红石信号">§10.3 红石信号</a></li>
    <li><a href="#方块交互">§10.4 方块交互</a></li>
    <li><a href="#生物移动">§10.5 生物移动</a></li>
    <li><a href="#交易">§10.6 交易</a></li>
    <li><a href="#清理特定物品">§10.7 清理特定物品</a></li>
    <li><a href="#连锁">§10.8 连锁</a></li>
  </ul></li>
  <li><a href="#算法">§11 算法</a><ul>
    <li><a href="#随机数">§11.1 随机数</a><ul>
      <li><a href="#不定长均匀分布">§11.1.1 不定长均匀分布</a></li>
      <li><a href="#定长均匀分布">§11.1.2 定长均匀分布</a></li>
      <li><a href="#非均匀分布">§11.1.3 非均匀分布</a></li>
      <li><a href="#二项分布和泊松分布">§11.1.4 二项分布</a></li>
    </ul></li>
    <li><a href="#世界生成结构">§11.2 世界生成结构</a><ul>
      <li><a href="#自定义地物">§11.2.1 自定义地物</a></li>
      <li><a href="#任意纯方块结构">§11.2.2 任意纯方块结构</a></li>
      <li><a href="#含实体结构">§11.2.3 含实体结构</a></li>
      <li><a href="#区块标记法">§11.2.4 区块标记法</a></li>
    </ul></li>
    <li><a href="#维度探测">§11.3 维度探测</a></li>
    <li><a href="#绘制图案">§11.4 绘制图案</a></li>
    <li><a href="#循环与递归">§11.5 循环与递归</a></li>
    <li><a href="#字符操作">§11.6 字符操作</a></li>
    <li><a href="#位运算与种子">§11.7 位运算与种子</a></li>
    <li><a></a></li>
  </ul></li>
</ul>
<footer id="options">
<div style="background-color: rgb(0,0,129);" onclick="content_level_1(this);" title="显示目录全部层次">全</div>
<div style="background-color: rgb(0,0,129);display:none;" onclick="content_level_2(this)" title="显示目录节">节</div>
<div style="background-color: rgb(0,0,129);display:none;" onclick="content_level_3(this);" title="显示目录小节">小</div>

<div style="background-color: rgb(0,129,0);" onclick="hidecomment(this);" title="显示JSON注释">显</div>
<div style="background-color: rgb(0,129,0);display:none;" onclick="showcomment(this)" title="隐藏JSON注释">隐</div>
</footer>
<footer id="sign">
<p class="noindent" style="font-size:100%;margin:0; text-align:right;color: hsl(220, 90%, 90%);">ruhuasiyu</p>
</footer>
</nav>

<div id="main_part">
<img id="banner" src="items/banner.png" alt="原版模组入门教程" style="width:100%;"/>

<article>
<p style="font-style: italic;">最后更新于 2022/04/23</p>
<h1 id="引言">§1 引言</h1>
<p>原版模组指在不修改 Minecraft 游戏本体的前提下，通过命令方块、一键命令、数据包、资源包等方式对游戏的可玩性做出修改。之所以称之为原版模组，乃是为了和使用 Mod Loader/API 环境基于 Java 开发的 Mod 作区分，这些 Mod Loader/API 包括 Forge，Liteloader，Fabric 等。自 Minecraft Java 版 1.13 起的数据包概念问世之后，原版模组的制作已变得十分便捷。本文内的原版模组便是指利用数据包和可能的配套资源包对游戏的可玩性做出修改。</p>

<p>本文内容适用于 Minecraft Java 版 1.19 版本，但大部分内容也适合 1.13-1.18 版本，或只需要做简单修改，请读者自行区分。系统环境为 Windows 10，其它环境下有较小的差异。本文参考和吸取了大量其他玩家的意见、建议和教程等，无法一一列出，在此一并表示感谢。</p>

<p>本文更侧重教程而非开发手册，因此很多内容的完整格式并没有列出，此时请读者自行查阅相关的<a href="https://zh.minecraft.wiki">中文 Minecraft Wiki</a> 链接。由于<a href="https://minecraft.wiki">英文 Minecraft Wiki</a> 往往更新更及时且内容更准确，因此有英文阅读能力的可直接查看英文 wiki 的相关内容。</p>

<p>本文中<code><i>青铜色楷体</i></code>表示其应当被替换为合适的字符串，<code style="color: rgb(0,129,0);">绿色楷体</code>表示JSON文件中的注释，点击左下角<span style="color:white;background-color: rgb(0,129,0);font-weight: bold;">显</span>/<span style="color:white;background-color: rgb(0,129,0);font-weight: bold;">隐</span>可切换显示或隐藏注释。</p>

<h2 id="命令基础">§1.1 命令基础</h2>
<p>本文不会介绍命令的基础知识，相关内容请读者通过如下链接自行了解。</p>
<ul>
  <li><a href="https://zh.minecraft.wiki/w/命令">命令</a>
    此为官方 wiki 的命令页面，其中包括了命令的基本参数介绍：坐标、目标选择器、数据标签 (NBT) 、原始JSON文本、命名空间ID等内容。读者需在学习命令过程中逐步了解这些概念。</li>
  <li><a href="https://zh.minecraft.wiki/w/记分板">记分板</a>
    此为官方 wiki 的记分板页面，其中包括了记分板的所有准则和相关命令格式，也包含了标签 (tag) 和组 (team) 的相关内容。</li>
  <li><a href="https://zh.minecraft.wiki/w/实体格式">实体格式</a>和<a href="https://zh.minecraft.wiki/w/Player.dat格式">player.dat格式</a>
    这两个页面给出了所有物品和实体(含方块实体)的 NBT。在游戏中，实体的 NBT 可通过命令 <code>data get entity/block</code> 来获取，物品的 NBT 可通过手持并输入命令 <code>data get entity @s SelectedItem</code> 来获取，以避免记忆大量的 NBT。</li>
  <li><a href="https://commandtutorials.neocities.org/">新人手册-MC命令方块资源</a>
    该网站包含了很多基础的教程，不过很多内容会有些过时。还包含少量进阶的内容，对于初学者可能较为复杂，请以理解其逻辑为主。</li>
  <li><a href="http://mc-command.oschina.io/command-tutorial/">命令进阶</a>
    该网站虽名为命令进阶，实际上比前一项页面更为初等，不过更为系统。</li>
</ul>
<p>若你已对 1.18 之前版本的命令较为熟悉，可在<a href="https://zh.minecraft.wiki/w/Java版版本记录">Java版版本记录</a>中查看各版本间差异。</p>

<h2 id="工具准备">§1.2 工具准备</h2>
<h3 id="文本编辑器">§1.2.1 文本编辑器</h3>
<p>原版模组涉及的文本文件，包括文本文档(.txt)、函数文件(.mcfunction)、JSON文件(.json, .mcmeta)、顶点着色器(.vsh)和片段着色器(.fsh)，均需使用 <code>UTF-8</code> 编码格式。注意不要误选了 <code>UTF-8 with BOM</code> 编码格式。文本编辑器多如瀚海，读者可自行选择一种。我仅列出本人常用的两个文本编辑器。</p>
<ul>
  <li><a href="https://code.visualstudio.com/">Visual Studio Code</a> 下载安装后，可以安装插件 <em>Chinese (Simplified) Language Pack for Visual Studio Code</em> 以支持中文语言，以及<em>Data-pack Helper Plus</em> 用于数据包各项内容的语法补全和纠错。</li>
  <li>记事本为 Windows 系统自带的极简编辑器。Windows10 的记事本已经默认是 <code>UTF-8</code> 编码了。点击<code>查看->状态栏</code>可以在右下角状态栏看到，因此可以正常使用。旧版本 Windows 的记事本仍然不是，请勿使用。</li>
  <!--<li><a href="https://notepad-plus-plus.org/">Notepad++</a>复杂程度介于二者之间。可从 <a href="http://www.mcbbs.net/thread-806816-1-1.html">mcfunction 的语言样式和自动补全</a>帖中下载相关文件并导入以支持语法高亮和补全。另外请将 Notepad++ 中<code>设置->首选项->其它->自动检测字符编码</code>选项关闭。</li>-->
</ul>
<p>编辑器右下角可以看到 <code>LF</code> 或 <code>CRLF</code>，分别表示两种换行符，二者均可正常使用，建议使用 <code>LF</code>。</p>
<p>为便于查看文件后缀，请将<code>文件->文件夹选项->查看->隐藏已知文件类型的扩展名</code>去掉勾选。我们可以在编辑器中新建文本文件，或者在文件夹中<code>右键->新建->文本文档</code>，除 <code>txt</code> 以外的文本文件可通过修改文件后缀得到。</p>

<h3 id="压缩软件">§1.2.2 压缩软件</h3>
<p>数据包和资源包均可以为文件夹或 zip 文件，zip 文件需要压缩软件来打开和制作。游戏本体和模组本体的 jar 文件也需要使用压缩软件来打开。常见的压缩软件有：</p>
<ul>
  <li><a href="http://www.7-zip.org/">7-Zip</a> 是一款免费的压缩软件。jar 文件可以通过<code>右键->7-zip->打开压缩包</code>来打开。</li>
  <li><a href="http://www.winrar.com.cn/">WinRAR</a> 是一款付费的压缩软件。</li>
  <li>Windows 资源管理器是 Windows10 系统自带的软件。它可以使得 zip 文件如同文件夹般直接打开，压缩则用<code>选择->右键->发送到->压缩文件夹</code>，但它的压缩速度十分缓慢。</li>
</ul>

<h3 id="NBT_编辑器">§1.2.3 NBT 编辑器</h3>
<p>我们可以使用 <a href="https://github.com/tryashtar/nbt-studio/releases/">NBTStudio</a> 来打开 dat 文件和其它 NBT 格式文件。</p>

<h3 id="绘图工具">§1.2.4 绘图工具</h3>
<p>我们可以使用 <a href="https://www.adobe.com/cn/products/photoshop.html">Adobe Photoshop</a> 或其它绘图工具来绘制纹理。Windows 自带的画图由于无法生成透明背景，因此不建议使用。</p>

<h2 id="文件结构">§1.3 游戏文件夹</h2>
<p>本节中我们将对游戏文件夹的结构做简单的介绍，我们只介绍原版模组开发中涉及的内容。<code>.minecraft</code> 文件夹是 Minecraft 创建的并用于游戏运行的文件夹，它包含了游戏的所有内容。在第一次启动启动器时，会自动创建 <code>.minecraft</code> 文件夹。参考 <a href="https://zh.minecraft.wiki/w/.minecraft" class="wiki">.minecraft</a>。</p>

<p><code>.minecraft</code> 文件夹通常位于你的启动器目录下。如果启动器中设置为各版本独立，则位于 <code>versions/<i>版本号</i></code>下。另一种方式是在游戏内点击<code>选项->资源包->打开压缩包文件夹</code>并返回上级目录，或者点击<code>单人游戏->选中世界->编辑->打开世界文件夹</code>并返回上上级目录。</p>

<p class="noindent" id="游戏本体"><strong>游戏本体</strong>位于 <code>versions/<i>版本号</i>/<i>版本号</i>.jar</code>。该文件包含了对应版本的游戏资源和数据文件，使用压缩软件打开后，可以看到</p>
<ul>
  <li>原版<a href="#资源包">资源包</a>位于 <code>assets</code> 文件夹内，其中 <code>minecraft</code> 文件夹为命名空间 <code>minecraft</code> 下的资源文件。</li>
  <li>原版<a href="#数据包">数据包</a>位于 <code>data</code> 文件夹内，其中 <code>minecraft</code> 文件夹为命名空间 <code>minecraft</code> 下的数据文件。</li>
  <li><code>pack.mcmeta</code> 为原版资源包和数据包的<a href="#数据包/元信息和图标">元信息</a>，1.17版本起不再包含该文件。</li>
  <li><code>pack.png</code> 为原版资源包和数据包的<a href="#数据包/元信息和图标">图标</a>。</li>
</ul>

<figure>
  <img src="items/游戏本体文件结构.png" alt="游戏本体文件结构" />
  <figcaption>图1.1 游戏本体文件结构</figcaption>
</figure>

<p class="noindent" id="资源包文件夹"><strong>资源包文件夹</strong>位于 <code>resourcepacks</code>，其下方子文件夹或 <code>zip</code> 文件即为一个资源包，具体结构见<a href="#资源包">资源包</a>。服务器下载的资源包位于 <code>server-resource-packs/<i>服务器</i></code>，可使用压缩软件打开。</p>

<p class="noindent" id="资源文件"><strong>资源文件</strong> 部分资源文件不被包含在原版资源包内，而是位于资源文件夹下，这主要包括各种语言文本和音效文件。资源文件索引位于 <code>assets/indexes/<i>版本号</i>.json</code>，打开后通过键值可知相应资源的 hash 值，对应的资源位于 <code>assets/objects/<i>hash前2位</i>/<i>hash</i></code>。例如打开 <code>assets/indexes/1.17.json</code>，找到键 <code>minecraft/lang/zh_cn.json</code> 的 <code>hash</code> 为 <code>8fb4f6725d8317a37e7f823ff424e66a46b9ef75</code>，因此简体中文的语言文本位于文件夹 <code>assets/objects/8f/8fb4f6725d8317a37e7f823ff424e66a46b9ef75</code>，使用文本编辑器打开即可看到游戏内的所有名称的中文译名。注意该文件中的中文均被转化成了相应的 Unicode 表达方式，参考<a href="#字体">字体</a>。</p>

<p class="noindent"><strong>日志</strong>位于 <code>logs/latest.log</code>，可由此实时查看游戏运行中的各种反馈。对于我们而言，它可以在加载资源包和数据包时告诉我们它们是否有错误以及错误信息，包括错误的文件名称、位置、错误的行列数等，因此这对于我们调试非常重要。简体中文下需要设置文件编码为 <code>gbk</code>，否则除 ASCII 外的字符会显示乱码。历史日志位于 <code>logs/<i>年</i>-<i>月</i>-<i>日</i>-<i>序号</i>.log.gz</code>，使用压缩软件打开后使用文本编辑器打开即可查看。崩溃报告位于 <code>crash-reports/crash-<i>年</i>-<i>月</i>-<i>日</i>_<i>时</i>.<i>分</i>.<i>秒</i>-server.txt</code>，如果是由于资源包或数据包引起的崩溃，可以在该文件中看到原因。</p>

<p class="noindent"><strong>存储的物品栏</strong>位于 <code>hotbar.nbt</code>，存储了游戏内使用 <code>C+<i>数字</i></code> 存储、<code>X+<i>数字</i></code> 取出的创造模式物品快捷栏。</p>

<p class="noindent"><strong>存档文件</strong>位于 <code>saves/<i>世界名称</i></code>，由于<a href="https://zh.minecraft.wiki/w/世界格式">世界格式</a>上该内容已较为详尽且与原版模组联系甚远，因此我们仅提及部分内容。该文件夹包含的区块文件、地图文件等内容虽然也可以使用 NBT 编辑器来编辑，但较为不便，我们建议使用 MCEdit、地图文件生成工具等专门的工具来编辑。存档的备份文件位于 <code>backups/<i>年</i>-<i>月</i>-<i>日</i>_<i>时</i>.<i>分</i>.<i>秒</i>_<i>世界名称</i>.zip</code>，为存档的备份文件，解压后复制到 <code>saves</code> 即可使用。</p>
<ul>
  <li><strong>进度</strong>位于 <code>advancements/<i>玩家UUID</i>.json</code>，记录了玩家已完成的进度和进度判据的完成时间。对于需要完成多个判据才能达成的进度，该文件中记录了已完成的那些判据的完成时间。</li>
  <li><strong><a href="https://zh.minecraft.wiki/w/%E5%8C%BA%E5%9D%97%E6%A0%BC%E5%BC%8F">区块</a>、实体、实体兴趣点、<a href="https://zh.minecraft.wiki/w/Raids.dat%E6%A0%BC%E5%BC%8F">袭击</a></strong>等信息分维度存储，主世界、下界、末地、自定义维度的相应文件分别位于根文件夹、<code>DIM-1</code>、<code>DIM1</code>、<code>dimensions/<i>命名空间</i>/<i>路径</i></code>下。</li>
  <li><strong>世界信息</strong>文件 <code>level.dat</code> 中 <code>WorldGenSettings</code> 包含了世界生成时的所有维度的生成信息，玩家可以在<code>创建新的世界->更多世界的选项->导入设置</code>使用JSON文件导入，格式见<a href="#自定义世界">自定义世界</a>。之后还会加入数据包中的自定义维度。</li>
  <li><strong>数据包文件夹</strong>位于 <code>datapacks</code>，其下方子文件夹或 <code>zip</code> 文件即为一个数据包，具体结构见<a href="#数据包">数据包</a>。</li>
  <li><strong>结构</strong>位于 <code>generated/<i>命名空间</i>/structures/<i>文件</i>.nbt</code>，其记录了游戏内使用结构方块保存的结构，将其移动至数据包内方可使用。</li>
</ul>

<h3 id="JSON文件">§1.4 JSON文件</h3>
<p>参考<a href="https://zh.minecraft.wiki/w/JSON" class="wiki">JSON</a>。数据包的进度、战利品表、战利品表谓词、物品修饰器、配方、标签、维度、维度类型、自定义世界生成，资源包的语言文件、模型、音效、字体、<code>credits.json</code> 等文件均为JSON文件。<code>.mcmeta</code> 文件也是JSON文件，因此格式也是相同的。</p>
<p>JSON文件中用于分割的空格、制表符(Tab)、回车和换行符都是可去的，它们仅用于提高可读性。编写时，使用空格或制表符缩进，以便于查看括号匹配和层次。JSON文件通常包含用于封装文件数据的一对大括号<code>{}</code>，即它是一个JSON对象，但<a href="#战利品表谓词">战利品表谓词</a>和<a href="#物品修饰器">物品修饰器</a>文件的根数据类型还可以为JSON数组。它包含类似 <code>"abc": "def"</code> 这样的 <code>"键": 值</code> 对，一般使用单引号也可以。同一个文件中如果允许有相同的键，则后者会覆盖前者。</p>
<p>JSON数据类型有下述几种。Wiki 上有关页面使用了 NBT 的数据类型标注，但其实并不适用于JSON文件，我们应当将其视为相应内容的可取值范围。</p>

<p class="noindent"><strong id="JSON布尔型">布尔型</strong>，值为 <code>true</code> 和 <code>false</code>。</p>
<pre>
{
  "is_on_fire": false,
  "is_baby": true,
  "noise_caves_enabled": false
}
</pre>
<p class="noindent"><strong id="JSON数值">数值</strong>，值为任何数字。<code>2</code> 和 <code>2.0</code> 没有差异。</p>
<pre>
{
  "count": 2.0,
  "chance": 0.025,
  "salt": 14357619
}
</pre>
<p class="noindent"><strong id="JSON字符串">字符串</strong>，值使用双引号/单引号圈住，可以使用颜色代码如 <code>§6</code>、换行符 <code>\n</code>。</p>
<pre>
{
  "condition": "minecraft:random_chance",
  "tag": "minecraft:wools",
  "layer0": "cpp:crop/bauhinia_seeds"
}
</pre>
<p class="noindent"><strong id="JSON数组">数组</strong>，值使用中括号圈住。</p>
<pre>
{
  "scale": [
    0.901,
    0.901,
    0.901
  ],
  "items": [
    "minecraft:zombie_head",
    "minecraft:skeleton_skull",
    "minecraft:wither_skeleton_skull",
    "minecraft:creeper_head"
  ],
  "requirements": [
    [
      "wing_of_sky",
      "heart_of_crystal",
      "nova_of_fire"
    ]
  ],
  "terms":[
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "biome": "minecraft:snowy_taiga"
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "biome": "minecraft:snowy_taiga_mountains"
      }
    }
  ]
}
</pre>
<p class="noindent"><strong id="JSON对象">对象</strong>，使用大括号圈住。整个JSON文件内容本身就是一个JSON对象。</p>
<pre>
{
  "count": {
    "type": "minecraft:uniform",
    "min": 1.0,
    "max": 2.0
  },
  "modifiers": [
    {
      "name": "legs_armor",
      "attribute": "generic.armor",
      "operation": "addition",
      "amount": 4,
      "slot": "legs"
    }
  ]
}
</pre>
<p>JSON中没有注释的语法，但可以使用不被使用的键来表示注释。通常使用 <code>"_comment", "_comment1", "_comment2"</code> 这种键。</p>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          <span class="comment">"_comment": "咸味粽子",</span>
          "type": "minecraft:item",
          "name": "minecraft:cooked_cod",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{display:{Name:'{\"italic\":false,\"translate\":\"item.cpp.zongzi_with_salt\"}',Lore:['{\"italic\":false,\"translate\":\"item.cpp.zongzi_with_salt\"}']},id:'cpp:zongzi_with_salt',CustomModelData:12970027}"
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<p>我们常常在JSON中用整数来表示RGB格式颜色，对应值为: <code>65536×R+256×G+B</code>。</p>

<h1 id="数据包">§2 数据包</h1>

<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/数据包" class="wiki">数据包</a></li>
  <li><a href="https://zh.minecraft.wiki/w/教程/安装数据包" class="wiki">教程/安装数据包</a></li>
  <li><a href="https://zh.minecraft.wiki/w/教程/制作数据包" class="wiki">教程/制作数据包</a></li>
</ul>
<p>数据包 (datapacks) 可用于覆盖或添加新的函数、进度、战利品表、战利品表谓词、物品修饰器、配方、结构、标签、维度、维度类型和自定义世界生成。数据包文件夹位于 <code>.minecraft/saves/<i>世界名称</i>/datapacks</code>，其下方子文件夹或 <code>zip</code> 文件即为一个数据包。</p>

<p>安装数据包：单人游戏中，对于新创建的世界，在创建时点击<code>创建新的世界->世界预设->数据包</code>，将数据包拖入并选择至右侧即可。对于已生成的世界，选择你需要安装数据包的世界，点击<code>编辑->打开世界文件夹->打开文件夹 datapacks</code>，并将数据包 <code>.zip</code> 文件或文件夹放入其中。多人游戏中，打开<code>服务器文件夹->worlds->datapacks</code>文件夹，并将数据包 <code>.zip</code> 文件或文件夹放入其中。数据包放置好后，在首次生成该世界/重新进入该世界/下次服务器启动时会启用该数据包。管理员也可以输入 <code>/reload</code> 来加载数据包，但这不适用<a href="#维度">维度</a>和<a href="#自定义世界生成">自定义世界生成</a>。</p>

<p>原版数据包是 Minecraft 自带的一个默认开启的数据包，其 <code>data</code> 文件夹位于 <code>.minecraft/versions/<i>版本号</i>/<i>版本号</i>.jar/data</code>，其中包含的原版进度、战利品表、配方、结构和标签等内容，是制作数据包的文件样板。注意原版的维度和自定义世界生成不在该路径，可从<a href="vanilla_worldgen.zip">此处下载</a>这些内容。</p>

<p>对于创建世界时添加的数据包，可以在数据包选择页面调整加载次序。其它情形添加的数据包优先级最高，即最后加载。同时加入的数据包优先级则和文件名顺序相关。数据包的优先级顺序储存在文件 <code>level.dat</code> 中，可以通过 <code>/datapack</code> 命令查看或修改。在游戏中通过命令 <code>/datapack</code> 可以禁用/启用数据包，最后启用的优先级最高。由于数据包加载顺序不定，因此在制作数据包的过程中，尽量不要依赖数据包的加载顺序。原版数据包的优先级一般是最低的。</p>
<p>使用 <code>/datapack list</code> 命令显示数据包名称时，原版数据包为 <code>[vanilla]</code>，玩家自定义的数据包为 <code>[file/<i>数据包名称</i>]</code>。</p>

<p class="noindent"><strong>文件夹结构</strong></p>
<pre class="file">datapacks/<i>数据包名称</i>或<i>数据包名称</i>.zip/</pre>
<pre>
pack.mcmeta
pack.png
data
  <i>命名空间</i>
    advancements
      <i>进度名称</i>.json
    functions
      <i>函数名称</i>.mcfunction
    loot_tables
      <i>战利品表名称</i>.json
    predicates
      <i>战利品表谓词名称</i>.json
    item_modifiers
      <i>物品修饰器名称</i>.json
    structures
      <i>结构名称</i>.nbt
    recipes
      <i>配方名称</i>.json
    tags
      functions
        <i>函数标签名称</i>.json
      blocks
        <i>方块标签名称</i>.json
      items
        <i>物品标签名称</i>.json
      entity_types
        <i>实体类型标签名称</i>.json
      fluids
        <i>流体标签名称</i>.json
      game_events
        <i>游戏事件标签名称</i>.json
    dimension
      <i>维度名称</i>.json
    dimension_type
      <i>维度类型名称</i>.json
    worldgen‌
      noise_settings
        <i>噪声设置名称</i>.json    
      biome
        <i>生物群系名称</i>.json
      configured_carver
        <i>地形雕刻器名称</i>.json
      configured_surface_builder
        <i>地表生成器名称</i>.json
      configured_feature
        <i>地物名称</i>.json
      configured_structure_feature
        <i>结构地物名称</i>.json
      template_pool
        <i>模板池名称</i>.json
      processor_list
        <i>处理器列表名称</i>.json
</pre>
<p>由于命名空间ID的命名要求，<code>data</code> 下所有文件和文件夹可使用的字符为 <code>_-.abcdefghijklmnopqrstuvwxyz0123456789</code>，<strong>不可使用大写字母、空格或中文</strong>，所有文本文件使用 <code>UTF-8</code> 编码。为了便于传播，发布时可将所有内容压缩为一个 <code>zip</code> 文件。压缩和解压的时候，注意文件层次，应当打开 <code>zip</code> 文件就可以看到数据包的 <code>pack.mcmeta</code>。稳妥的做法是 <code>打开文件夹->全选->右键->发送到->压缩文件夹</code> 或 <code>打开文件夹->全选->7-Zip->添加到 "<i>文件夹名</i>.zip"</code>。文件夹格式的数据包若有错误文件仍可以加载，但 <code>zip</code> 格式的会无法加载。</p>

<h2 id="数据包/元信息和图标">§2.1 元信息和图标</h2>
<p>Minecraft 通过文件 <code>pack.mcmeta</code> 来识别数据包，因此该文件是不可或缺的。例如：</p>
<pre class="file">pack.mcmeta</pre>
<pre>
{
  "pack": {
    "pack_format": 6, <span class="comment">数据包版本，1.13-1.14 版本为 4，1.15-1.16.1 版本为 5，1.16.2-1.16.5 版本为 6，1.17-1.17.1 版本为 7，1.18-1.18.1 版本为 8，1.18.2 版本为 9，1.19 版本为 10</span>
    "description": [<span class="comment">数据包描述</span>
      {
        "text": "数据包名称",
        "color": "green"
      },
      {
        "text": "简要介绍\nby 某某作者",
        "color": "gold"
      }
    ]
  },
  "filter": {
    "block": [<span class="comment">忽略相应命名空间下相应文件</span>
      {
        "namespace": "命名空间", 
        "path": "文件路径" <span class="comment">支持通用标识符 *</span>
      }
    ]
  }
}
</pre>
<p class="noindent">其中数据包描述为单个字符串或一个<a href="https://zh.minecraft.wiki/w/%E5%8E%9F%E5%A7%8BJSON%E6%96%87%E6%9C%AC%E6%A0%BC%E5%BC%8F">原始JSON文本</a>。创建新的世界时，它会显示在数据包菜单中数据包名称下方。在数据包列表下，光标移动到对应的数据包时会显示此处填写的描述。</p>

<p>1.16版本原版数据包里的 <code>pack.mcmeta</code> 文件为</p>
<pre class="file">pack.mcmeta</pre>
<pre>
{
  "pack": {
    "pack_format": 6,
    "description": "The default data for Minecraft"
  }
}
</pre>

<p>数据包可以包含一个 <a href="vanilla/pack.png"><code>pack.png</code></a>，它是正方形的图片，用于创建新的世界时在数据包菜单中显示。</p>

<h2 id="数据包/命名空间">§2.2 命名空间</h2>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/命名空间" class="wiki">命名空间</a></li>
</ul>
<p>命名空间 (namespace) 为玩家自定义的、可操作的空间。使用独立的命名空间也有利于解决和他人的冲突。数据包下可以有多个命名空间，如果不同数据包中有相同的命名空间，则其中相同的文件名内容会根据加载先后顺序被覆盖。特别地，原版内容被保存在 <code>minecraft</code> 命名空间，想要修改和替换原版的内容只需在你的数据包内建立 <code>minecraft</code> 命名空间和相应的同名文件并修改即可。</p>
<p><a href="#标签">标签</a>文件，即 <code>tags</code> 中的文件内容默认追加而不是覆盖。因此标签文件是解决数据包冲突和联动的有力工具。</p>

<table><thead><tr><th>类型</th><th>调用格式(命名空间ID)</th><th>文件路径</th></tr></thead><tbody>
<tr>
  <th>函数</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/functions/<i>路径</i>/<i>文件名</i>.mcfunction</code></td>
</tr>
<tr>
  <th>进度</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/advancements/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>战利品表</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/loot_tables/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>战利品表谓词</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/predicates/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>物品修饰器</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/item_modifiers/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>配方</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/recipes/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>结构</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/strutures/<i>路径</i>/<i>文件名</i>.nbt</code></td>
</tr>
<tr>
  <th>标签-方块</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/tags/blocks/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>标签-物品</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/tags/items/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>标签-函数</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/tags/functions/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>标签-实体类型</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/tags/entity_types/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>标签-流体类型</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/tags/fluids/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>标签-游戏事件</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/tags/game_events/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>维度</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/dimension/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>维度类型</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/dimension_type/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>世界生成-噪声设置</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/worldgen‌/noise_settings/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>世界生成-生物群系</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/worldgen‌/biome/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>世界生成-地形雕刻器</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/worldgen‌/configured_carver/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>世界生成-地表生成器</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/worldgen‌/configured_surface_builder/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>世界生成-地物</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/worldgen‌/configured_feature/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>世界生成-结构地物</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/worldgen‌/configured_structure_feature/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>世界生成-模板池</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/worldgen‌/template_pool/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>世界生成-处理器列表</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/worldgen‌/processor_list/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
</tbody></table>

<p>1.16~1.16.1 版本的维度、维度类型和世界生成文件位置为 <code>minecraft/<i>类型</i>/<i>命名空间</i>/<i>路径</i>/<i>文件名</i>.json</code> 而不是 <code><i>命名空间</i>/<i>类型</i>/<i>路径</i>/<i>文件名</i>.json</code>。</p>
<p>若命名空间为 <code>minecraft</code>，则可直接省略 <code>minecraft:</code>。本文中我们会混用两种写法，注意区分。除此之外，如战利品表的 <code>type</code>、战利品表谓词的 <code>condition</code> 等诸多情形的值也是 <code>minecraft</code> 命名空间下的命名空间ID，因此此时也可以省略 <code>minecraft:</code>。</p>

<h2 id="函数">§2.3 函数</h2>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/functions/<i>路径</i>/<i>文件名</i>.mcfunction</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/函数（Java版）" class="wiki">函数</a></li>
  <li><a href="https://minecraft.wiki/w/Function_(Java_Edition)" class="wikien">Function</a></li>
</ul>

<p>函数 (Function) 是一系列顺次执行的命令列表，可以被命令 <code>function <i>命名空间ID</i></code> 来依次执行函数的每一条命令，还可被调用于<a href="#进度">进度</a>JSON文件的 <code>rewards->function</code>。函数每一行表示一个单独的命令，无需 <code>/</code> 开头。执行时会按顺序依次执行，使用 <code>#</code> 开头的行是注释。</p>
<p>如果函数被另一个函数执行，则默认无执行者，执行位置为出生点，除非在执行时继承调用它的函数的执行者和执行位置。如果函数被命令方块执行，则无执行者，执行位置为命令方块位置。如果函数被玩家手动执行，则执行者为玩家自身，执行位置为玩家位置。如果函数被进度奖励，执行者为完成进度的玩家，执行位置为玩家位置。这些情形下的执行者和执行位置均可使用<a href="https://zh.minecraft.wiki/w/命令/execute">命令</a> <code>execute</code> 来改变。</p>

<p>如果需要函数在游戏加载/每刻执行，则需要将其加入<a href="#函数标签">函数标签</a>中。</p>

<pre class="file" id="#cpp/functions/plants/vegt">cpp:plants/vegt</pre>
<pre>
<span class="comment">幻紫花</span>
execute as @s[tag=cpp_crop_purple_illusion] if predicate cpp:near_purple run function cpp:plants/vegt/purple_illusion
<span class="comment">稻谷</span>
execute as @s[tag=cpp_crop_rice] if block ~ ~-1 ~ farmland if predicate cpp:near_water run function cpp:plants/vegt/rice
<span class="comment">西红柿</span>
execute as @s[tag=cpp_crop_tomato] if block ~ ~-1 ~ farmland run function cpp:plants/vegt/fruit
<span class="comment">草莓</span>
execute as @s[tag=cpp_crop_strawberry] if block ~ ~-1 ~ farmland run function cpp:plants/vegt/fruit
<span class="comment">蓝莓</span>
execute as @s[tag=cpp_crop_blueberry] if block ~ ~-1 ~ podzol run function cpp:plants/vegt/fruit
<span class="comment">菠萝</span>
execute as @s[tag=cpp_crop_pineapple] if block ~ ~-1 ~ coarse_dirt if predicate cpp:near_water run function cpp:plants/vegt/fruit
</pre>

<h2 id="进度">§2.4 进度</h2>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/advancements/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/进度/JSON格式" class="wiki">进度</a></li>
  <li><a href="https://minecraft.wiki/w/Advancement/JSON_format" class="wikien">Advancement</a></li>
</ul>

<p>进度 (Advancement) 为游戏内检测玩家行为，触发后完成并执行奖励的系统，游戏内按 <code>L</code> 即可查看，可被用作命令 <code>advancement</code> 的参数，以授予或移除玩家的特定进度。</p>
<p>注意1.17的物品谓词和方块谓词与旧版本的有差异。</p>
<pre class="file" id="进度JSON格式">进度JSON格式</pre>
<pre>
{
  "display": { <span class="comment">可选，显示数据</span>
    "icon": { <span class="comment">一个物品，用于显示进度的图标</span>
      "item": "物品命名空间ID", <span class="comment">图标物品 ID</span>
      "nbt": "字符串" <span class="comment">图标物品nbt标签，可能会影响图标，例如指定 CustomModelData</span>
    },
    "title": <a href="https://zh.minecraft.wiki/w/原始JSON文本格式">原始JSON文本</a>, <span class="comment">进度的名称</span>
    "description": <a href="https://zh.minecraft.wiki/w/原始JSON文本格式">原始JSON文本</a>, <span class="comment">进度的描述</span>
    "frame": "task" (默认) 或 "challenge" 或 "goal", <span class="comment">可选，图标边框，分别为方形边框(任务)、尖形边框(挑战)、圆形边框(目标)</span>
    "background": "<a href="#纹理">纹理</a>命名空间ID", <span class="comment">仅根进度有，决定该选项卡的背景图</span>
    "show_toast": true (默认值) 或 false, <span class="comment">可选，是否在完成此进度后显示提示信息，若无显示效果则无效。</span>
    "announce_to_chat": true (默认值) 或 false, <span class="comment">可选，是否在完成此进度时在聊天窗口提示，若无显示效果则无效。</span>
    "hidden": true 或 false (默认值), <span class="comment">可选，在进度屏幕隐藏此进度和子进度，直到完成进度。</span>
  },
  "parent": "<a href="#进度">进度</a>命名空间ID", <span class="comment">可选，表示上游进度</span>
  "criteria": { <span class="comment">需要达成的条件</span>
    "条件名称": { <span class="comment">其中一个条件</span>
      "trigger": "触发器名称", 
      "conditions": { <span class="comment">该触发器达成时需要满足的条件</span>
      }
    }
  },
  "requirements": [ <span class="comment">可选，每一组条件中至少有一个达成时，该进度才会完成。默认所有条件都需要达成。</span>
    [
      "条件", ..., "条件"
    ],
    [
      "条件", ..., "条件"
    ]
  ],
  "rewards": { <span class="comment">可选, 完成进度的奖励</span>
    "function":
      "<a href="#函数">函数</a>命名空间ID", <span class="comment">完成进度时执行该函数，不可为函数标签。</span>
    "loot": [ <span class="comment">完成进度时给予玩家这些战利品表</span>
      "<a href="#战利品表">战利品表</a>命名空间ID", ..., "<a href="#战利品表">战利品表</a>命名空间ID"
    ],
    "recipes": [ <span class="comment">完成进度时玩家解锁这些配方</span>
      "<a href="#配方">配方</a>命名空间ID", ..., "<a href="#配方">配方</a>命名空间ID"
    ],
    "experience": 正整数 <span class="comment">完成进度时玩家获得的经验</span>
  }
}
</pre>

<p>没有 <code>parent</code> 的进度被称为根进度。若其有 <code>display</code>，则它定义了一个进度的选项卡。</p>
<p>当一个进度没有 <code>display</code> 时，或者其上游的根进度没有 <code>display</code> 时，它不会显示在进度页面中。解锁配方的进度，以及我们只是用来实现某些效果而并非希望将其添加到进度页面的进度，应当省略 <code>display</code> 以隐藏之。</p>
<p>当进度需要所有的条件都达成时才能完成时，我们不需要定义 <code>requirements</code>，这等价于 <code>"requirements": [["条件 1"],["条件 2"],...,["条件 n"]]</code>。如果我们需要复杂的组合条件时，就需要使用该字段。<code>requirements</code> 的格式为或的与(合取范式)，即其列表中的每一个项(该项还是一个条件的列表)中的均至少有一个条件满足。例如 <code>"requirements": [["条件 a", "条件 b"],["条件 c", "条件 d"]]</code> 表示当 <code>条件 a</code> 和 <code>条件 b</code> 至少有一个满足且 <code>条件 c</code> 和 <code>条件 d</code> 至少有一个满足时，进度会完成。不过较为常见的还是所有条件只要有一个满足即可，这时写作 <code>"requirements": [["条件 1","条件 2",...,"条件 n"]]</code>。例如下例中两个条件 <code>sealing_wand</code>, <code>dream_wand</code> 分别表示玩家获取了相应 NBT 物品的触发器，只要其中有一个满足即可完成进度。</p>

<pre class="file" id="cpp/advancements/wand">cpp/advancements/wand.json</pre>
<pre>
{
  "parent": "cpp:root",
  "display": {
    "icon": {
      "item": "minecraft:carrot_on_a_stick",
      "nbt": "{CustomModelData:12970062}"
    },
    "title":{
      "translate": "advancements.cpp.wand.title"
    },
    "description": {
      "translate": "advancements.cpp.wand.description"
    },
    "frame": "challenge"
  },
  "criteria": {
    "sealing_wand": {
      "trigger": "minecraft:inventory_changed",
      "conditions":{
        "items":[
          {
            "nbt": "{id:\"cpp:sealing_wand\"}"
          }
        ]
      }
    },
    "dream_wand": {
      "trigger": "minecraft:inventory_changed",
      "conditions":{
        "items":[
          {
            "nbt": "{id:\"cpp:dream_wand\"}"
          }
        ]
      }
    }
  },
  "rewards": {
    "experience": 200
  },
  "requirements": [
    [
      "mahoushoujo",
      "dream_wand"
    ]
  ]
}</pre>

<p>完整的触发器和触发器的条件请查看<a href="https://zh.minecraft.wiki/w/进度/JSON格式#触发器列表">进度/JSON格式#触发器列表</a>。我们简要列出常见的触发器：</p>

<table><thead><tr><th>触发器</th><th>触发器的条件</th></tr></thead><tbody>
<tr>
  <td><code>minecraft:impossible</code></td>
  <td>仅可使用命令触发。这样的进度一般使用函数来判断并直接给予玩家。</td>
</tr>
<tr>
  <td><code>minecraft:tick</code></td>
  <td>每个游戏刻触发。常用于判断玩家是否是第一次进入游戏。也可用来仅需判断玩家的战利品表谓词来完成的进度，见下文。</td>
</tr>
<tr>
  <td><code>minecraft:location</code></td>
  <td>检查玩家的位置，例如玩家进入某个维度、生物群系、结构等，或者玩家进入某种流体、某个高度等。有些也可以用其它触发器实现。</td>
</tr>
<tr>
  <td><code>minecraft:enter_block</code></td>
  <td>玩家进入方块时触发，例如水、传送门、花等。</td>
</tr>

<tr>
  <td><code>minecraft:placed_block</code></td>
  <td>玩家放置方块时触发，例如玩家放置了木桶、熔炉、树苗等。在我们自定义方块时很有用。该进度被触发时，方块已经被放置在世界中但玩家手持的方块尚未被清除，因此可以检测玩家手持物的信息。</td>
</tr>
<tr>
  <td><code>minecraft:inventory_changed</code></td>
  <td>玩家物品栏变化时触发，例如玩家获取物品。</td>
</tr>
<tr>
  <td><code>minecraft:consume_item</code></td>
  <td>玩家消耗了相应物品，例如食用食物、饮用药水等。在我们自定义食物和药水时很有用。该进度被触发时，玩家手持的物品尚未被消耗，因此可以检测玩家手持物的信息。</td>
</tr>

<tr>
  <td><code>minecraft:entity_hurt_player</code></td>
  <td>实体伤害玩家时触发。</td>
</tr>
<tr>
  <td><code>minecraft:entity_killed_player</code></td>
  <td>实体杀死玩家时触发。</td>
</tr>
<tr>
  <td><code>minecraft:player_hurt_entity</code></td>
  <td>玩家伤害实体（包括自己）时触发。</td>
</tr>
<tr>
  <td><code>minecraft:player_killed_entity</code></td>
  <td>玩家杀死实体时触发。</td>
</tr>
<tr>
  <td><code>minecraft:player_interacted_with_entity</code></td>
  <td>玩家用手中物品与实体互动时触发，例如交易、修改实体数据(驯服、喂养、上鞍、剪羊毛、旋转物品展示框或放入物品、收集龙息、与猪灵换物、修补铁傀儡)、桶装牛奶、桶装鱼、碗装蘑菇煲、碗装迷之炖菜等。</td>
</tr>

<tr>
  <td><code>minecraft:item_durability_changed</code></td>
  <td>物品栏中任何物品以任何形式损害时触发，例如使用工具消耗了耐久。当使用拥有耐久附魔的工具而未消耗耐久时，不会触发。</td>
</tr>
<tr>
  <td><code>minecraft:item_used_on_block</code></td>
  <td>玩家对方块使用物品时触发，例如对着篝火放置食物、斧给木头剥皮、向花盆中放入花等改变目标方块数据的，或者右击告示牌，或者对着任意方块放置方块。</td>
</tr>
</tbody></table>

<p>所有的触发器条件均有一个可选的<a href="#战利品表谓词">战利品表谓词</a>列表 <code>player</code> 字段用于要求玩家额外需要满足的战利品表谓词。例如</p>
<pre class="file" id="cpp/functions/fatness">cpp:fatness</pre>
<pre>
{
  "display": {
    "icon": {
      "item": "minecraft:enchanted_golden_apple"
    },
    "title":{
      "translate": "advancements.cpp.fatness.title"
    },
    "description": {
      "translate": "advancements.cpp.fatness.description"
    },
    "frame": "challenge"
  },
  "parent": "cpp:dream_wand",
  "criteria": {
    "fatness": {
      "trigger": "minecraft:tick",
      "conditions": {
        "player": [
          {
            "condition": "minecraft:entity_scores",
            "entity": "this",
            "scores": {
              "cppHealth": {
                "min": 40
              }
            }
          }
        ]
      }
    }
  }
}</pre>

<p>奖励中的解锁配方一般适用于数据包添加的配方相应的解锁进度，这样的进度无需 <code>display</code> 字段，参考<a href="#配方">配方</a>。奖励中的经验建议仅在高难度进度完成时给予，这样的进度通常设置 <code>frame</code> 为挑战。奖励中的函数的执行者为完成进度的玩家，位置为玩家的位置。</p>
  
<p>游戏内或函数内使用 <code>advancement</code> 命令可以手动给予或剥夺进度。进度配合奖励函数剥夺玩家该进度，则该进度可反复触发，可用于诸如检测玩家生物群系、饮食、放置方块等需要循环检测的情形。这样的进度需要缺省 <code>display</code> 字段。例如：</p>
<pre class="file" id="cpp/advancements/food/citrus">cpp/advancements/food/citrus.json</pre>
<pre>
{
  "criteria": {
    "citrus": {
      "trigger": "minecraft:consume_item",
      "conditions": {
        "item": {
          "nbt": "{id:\"cpp:citrus\"}"
        }
      }
    }
  },
  "rewards":{
    "function": "<a href="#cpp/functions/diet/citrus.mcfunction">cpp:diet/citrus</a>"
  }
}</pre>
<pre class="file" id="cpp/functions/diet/citrus.mcfunction">cpp:diet/citrus</pre>
<pre>
advancement revoke @s only <a href="#cpp/advancements/food/citrus">cpp:diet/citrus</a>
effect give @s saturation 1 1 true
</pre>

<p class="noindent"><strong id="原版进度">原版进度</strong> 如果需要修改原版的进度，只需要在数据包中添加相同路径的相应名称文件并修改之即可。原版的进度被划分为5个选项卡，命名空间ID分别为 <code>minecraft:story/*</code>, <code>minecraft:nether/*</code>, <code>minecraft:end/*</code>, <code>minecraft:adventure/*</code>, <code>minecraft:husbandry/*</code>。其中 <code>minecraft:nether/all_effects</code>, <code>minecraft:adventure/hero_of_the_village</code>, <code>minecraft:adventure/arbalistic</code> 为隐藏进度。这些进度没有奖励，或只有奖励经验值。</p>
<p>除此之外，原版获取配方的进度命名空间ID为 <code>minecraft:recipes/*</code>。</p>


<h2 id="战利品表">§2.5 战利品表</h2>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/loot_tables/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/战利品表" class="wiki">战利品表</a></li>
  <li><a href="https://minecraft.wiki/w/Loot_table" class="wikien">Loot table</a></li>
  <li><a href="http://www.mcbbs.net/thread-831542-1-1.html">战利品表：从入门到重新入门</a></li>
</ul>

<p>战利品表 (Loot table) 用于生成随机的一些物品，可作为容器的随机物品、实体的掉落物、方块的掉落物、钓鱼的战利品、猪灵以物换物的内容、猫和村民的礼物、进度的完成奖励、<code>loot</code> 命令的参数以给予玩家特定战利品表物品等。</p>
<ul>
  <li><code>setblock ~ ~ ~ chest{LootTable:"cpp:chests/something"}</code></li>
  <li><code>give @s barrel{BlockEntityTag:{LootTable:"cpp:chests/something"}}</code></li>
  <li><code>summon bat ~ ~ ~ {DeathLootTable:"cpp:entities/something"}</code></li>
  <li><code>loot spawn ~ ~ ~ loot cpp:something</code></li>
</ul>

<pre class="file" id="战利品表JSON格式">战利品表JSON格式</pre>
<pre>
{
  "type": <span class="comment">可选的战利品表种类，为 </span>"minecraft:empty"<span class="comment">无任何战利品</span>
  或 "minecraft:entity"<span class="comment">只可用于实体掉落物</span>
  或 "minecraft:block" <span class="comment">只可用于方块掉落物</span>
  或 "minecraft:chest"<span class="comment">只可用于箱子战利品表</span>
  或 "minecraft:fishing"<span class="comment">只可用于钓鱼战利品表</span>
  或 "minecraft:barter"<span class="comment">只可用于猪灵以物易物战利品表</span>
  或 "minecraft:gift"<span class="comment">只可用于猫或村民赠送的礼物战利品表</span>
  或 "minecraft:advancement_reward"<span class="comment">只可用于进度奖励</span>
  或 "minecraft:command"<span class="comment">只可用于命令</span>
  或 "minecraft:selector"<span class="comment">未知</span>
  或 "minecraft:advancement_entity"<span class="comment">未知</span>
  或 "minecraft:generic",<span class="comment">无限制，默认值</span>
  "functions": [<span class="comment">可选，将会应用到该战利品表所有物品的函数</span>
    <a href="#战利品表函数JSON对象">战利品表函数JSON对象</a>1,
    <a href="#战利品表函数JSON对象">战利品表函数JSON对象</a>2
  ],
  "pools": [<span class="comment">随机池列表，随机池之间相互独立</span>
    {
      "rolls": <a href="#值提供器">值提供器</a>, <span class="comment">指定在该随机池的抽取的次数</span>
      "bonus_rolls": <a href="#值提供器">值提供器</a>, <span class="comment">可选，默认为0，每点幸运提供的额外抽取次数。最终次数为 rolls+bonus_rolls×幸运 向下取整</span>
      "conditions": [<span class="comment">可选，抽取该随机池需要满足的条件</span>
        <a href="#战利品表条件JSON对象">战利品表条件JSON对象</a>1,
        <a href="#战利品表条件JSON对象">战利品表条件JSON对象</a>2
      ],
      "functions": [<span class="comment">可选，将会应用到该随机池所有物品的函数</span>
        <a href="#战利品表函数JSON对象">战利品表函数JSON对象</a>1,
        <a href="#战利品表函数JSON对象">战利品表函数JSON对象</a>2
      ],
      "entries": [<span class="comment">项目列表</span>
        {
          "conditions": [<span class="comment">可选，抽取该项目需要满足的条件，如果不满足，该项目会被忽略</span>
            <a href="#战利品表条件JSON对象">战利品表条件JSON对象</a>1,
            <a href="#战利品表条件JSON对象">战利品表条件JSON对象</a>2
          ],
          "type": 项目类型,
          "functions": [<span class="comment">可选，将会应用到该项目所有物品的函数</span>
            <a href="#战利品表函数JSON对象">战利品表函数JSON对象</a>1,
            <a href="#战利品表函数JSON对象">战利品表函数JSON对象</a>2
          ],
          "weight": <a href="#值提供器">值提供器</a>, <span class="comment">可选，默认为1，该项目的基础权重</span>
          "quality": <a href="#值提供器">值提供器</a>, <span class="comment">可选，默认为0，每点幸运属性对权重的加成, 最终被选中的概率为 (weight+quality×幸运)/所有项目(weight+quality×幸运)之和</span>
        }
      ]
    }
  ]
}
</pre>

<p>即使没有指定战利品表种类，或指定为 <code>minecraft:generic</code>，游戏也会根据实际应用的场景来决定它的类型。这意味着在相应情形无效的条件和函数不会生效，而且游戏不会报错提示。例如在方块战利品表中检测击杀者。</p>

<p><code>rolls</code>, <code>bonus_rolls</code>, 以及在战利品表、战利品表谓词和物品修饰器中的大部分数值可以有如下形式之一：</p>
<pre class="file" id="值提供器">值提供器</pre>
<pre>
    任意数值(可以为小数)
或  {<span class="comment">指定该数值为常数，和前面的写法等价</span>
      "type": "minecraft:constant",
      "value": 任意数值(可以为小数)
    }
或  {<span class="comment">指定该数值的范围</span>
      "type": "minecraft:uniform",
      "min": 任意数值(可以为小数),
      "max": 任意数值(可以为小数)
    }
或  {<span class="comment">指定该数值服从的二项分布</span>
      "type": "minecraft:binomial",
      "n": 任意数值(可以为小数), <span class="comment">尝试次数</span>
      "p": 0~1之间的小数 <span class="comment">每增加一次的概率</span>
    }
或  {<span class="comment">指定该数值来自于记分板</span>
      "type": "minecraft:score",
      "target": "this" 或 "killer" 或 "direct_killer" 或 "player_killer", <span class="comment">指定为该实体、杀死它的实体、直接杀死它的实体(例如箭), 杀死它的玩家</span>
    或
      "target": {
        "type": "context",
        "target": "this" 或 "killer" 或 "direct_killer" 或 "player_killer" <span class="comment">和前面的写法等价</span>
      或
        "type": "fixed",
        "name": "UUID或玩家名"
      },
      "objective": "记分板名称",
      "scale": 数值 <span class="comment">可选，放缩比例</span>
    }
</pre>

<p>项目会根据种类的不同而拥有不同的JSON格式：</p>
<pre class="file" id="战利品表项目">战利品表项目</pre>
<pre>
{
  "type": "minecraft:empty" <span class="comment">空</span>
}

{
  "type": "minecraft:item", <span class="comment">指定物品</span>
  "name": "物品命名空间ID"
}

{
  "type": "minecraft:loot_table", <span class="comment">指定战利品表</span>
  "name": "<a href="#战利品表">战利品表</a>命名空间ID"
}

{
  "type": "minecraft:tag", <span class="comment">指定物品标签</span>
  "name": "<a href="#物品标签">物品标签</a>命名空间ID",
  "expand": true 或 false <span class="comment">true 时，从该标签等概率随机选取一个；false 时，选出该标签下所有物品。</span>
}

{
  "type": "minecraft:alternatives", <span class="comment">从子项目中选取第一个满足条件的，这些子项目通常都指定了条件。</span>
  "children": [<span class="comment">项目列表</span>
    项目JSON对象1,
    项目JSON对象2
  ]
}

{
  "type": "minecraft:group", <span class="comment">从所有满足条件的子项目中随机选取，逻辑和随机池类似。</span>
  "children": [<span class="comment">项目列表</span>
    项目JSON对象1,
    项目JSON对象2
  ]
}

{
  "type": "minecraft:sequence", <span class="comment">从第一个条件不满足的子项目之前的所有的子项目中随机选取，即第一个不满足条件的子项目和之后的子项目会被忽略。</span>
  "children": [<span class="comment">项目列表</span>
    项目JSON对象1,
    项目JSON对象2
  ]
}

{
  "type": "minecraft:dynamic", <span class="comment">动态指定物品，一般只对原版的某些方块掉落物有效。</span>
  "name": "minecraft:self" <span class="comment">仅适用于玩家头颅、旗帜等，用于返回相同样式物品</span>
  或      "minecraft:content" <span class="comment">仅适用于潜影盒，用于返回潜影盒内所有物品</span>
}
</pre>

<p>我们在设计物品时，可以将物品信息打包成一个战利品表。之后我们便可以在其它战利品表中使用 <code>loot_table</code> 类型来方便地引用，见<a href="#物品设计">物品设计</a>。<code>alternatives</code> 类型在需要判断条件时很有用，例如原版的树叶掉落物就使用了该类型。当工具为剪刀或附有精准采集魔咒时，掉落树叶，否则掉落树苗。<code>dynamic</code> 类型配合潜影盒可以掉落不定 <code>id</code> 的物品，见<a href="#物品输出">物品输出</a>和<a href="#修改玩家背包">修改玩家背包</a>。</p>

<p class="noindent"><strong id="战利品表条件JSON对象">战利品表条件</strong> 用于对战利品表进行一些条件判断。仅当条件列表 <code>conditions</code> 中每一个条件都被满足时，其同层次的随机池/项目/函数才会被选取。战利品表条件和<a href="#战利品表谓词">战利品表谓词</a>JSON对象的格式完全相同。</p>

<p class="noindent"><strong id="战利品表函数JSON对象">战利品表函数</strong> 用于对战利品表进行一些修改。函数列表 <code>functions</code> 中每一个函数会依次应用于同层次的随机池/项目生成的战利品上，函数的不同顺序可能有不同效果。战利品表函数和<a href="#物品修饰器">物品修饰器</a>JSON对象的格式完全相同。</p>


<p>下面这个例子是对原版牛的掉落物进行的修改。</p>
<pre class="file" id="minecraft/loot_tables/entities/cow">minecraft/loot_tables/entities/cow.json</pre>
<pre>
{
  "type": "minecraft:entity",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:leather",
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": {
                "type": "minecraft:uniform",
                "min": 0,
                "max": 2
              }
            },
            {
              "function": "minecraft:looting_enchant",
              "count": {
                "type": "minecraft:uniform",
                "min": 0,
                "max": 1
              }
            }
          ]
        }
      ]
    },
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:alternatives",
          "children": [
            {
              "conditions": [
                {
                  "condition": "minecraft:entity_properties",
                  "entity": "this",
                  "predicate": {
                    "flags": {
                      "is_on_fire": false
                    }
                  }
                }
              ],
              "type": "minecraft:item",
              "name": "minecraft:beef",
              "functions": [
                {
                  "function": "minecraft:set_count",
                  "count": {
                    "type": "minecraft:uniform",
                    "min": 1,
                    "max": 3
                  }
                },
                {
                  "function": "minecraft:looting_enchant",
                  "count": {
                    "type": "minecraft:uniform",
                    "min": 0,
                    "max": 1
                  }
                }
              ]
            },
            {
              "type": "minecraft:item",
              "name": "minecraft:cooked_beef",
              "functions": [
                {
                  "function": "minecraft:set_count",
                  "count": {
                    "type": "minecraft:uniform",
                    "min": 1,
                    "max": 3
                  }
                },
                {
                  "function": "minecraft:looting_enchant",
                  "count": {
                    "type": "minecraft:uniform",
                    "min": 0,
                    "max": 1
                  }
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "conditions": [
        {
          "condition": "minecraft:killed_by_player"
        },
        {
          "condition": "minecraft:random_chance_with_looting",
          "chance": 0.025,
          "looting_multiplier": 0.01
        }
      ],
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:loot_table",
          "name": "cpp:limb_of_ridge"
        }
      ]
    },
    {
      "conditions": [
        {
          "condition": "minecraft:killed_by_player"
        },
        {
          "condition": "minecraft:random_chance_with_looting",
          "chance": 0.025,
          "looting_multiplier": 0.01
        }
      ],
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:loot_table",
          "name": "cpp:cow_head"
        }
      ]
    }
  ]
}
</pre>
<p>该例子战利品表表示牛死亡时</p>
<ul>
  <li>掉落 <code>0-(2+抢夺等级)</code>个皮革；</li>
  <li>掉落 <code>1-(3+抢夺等级)</code>个牛肉，着火则掉落熟牛肉；</li>
  <li>被玩家杀死时，有 <code>(2.5+抢夺等级)%</code> 几率掉落战利品表 <code>cpp:limb_of_ridge</code> 的物品；</li>
  <li>被玩家杀死时，有 <code>(2.5+抢夺等级)%</code> 几率掉落战利品表 <code>cpp:cow_head</code> 的物品。</li>
</ul>

<p>战利品表除上述用途外，还可用于生成随机数，见<a href="#随机数">随机数</a>；指定自定义机器的配方，见<a href="#配方处理">配方处理</a>等诸多场景。</p>

<p class="noindent"><strong id="原版战利品表">原版战利品表</strong>用于决定方块、实体的默认掉落物以及游戏的一些默认内容。如果需要修改原版的战利品表，只需要在数据包中添加相同路径的相应名称文件并修改之即可。原版的战利品表被划分为实体掉落物 <code>minecraft:entities/*</code>, 方块掉落物 <code>minecraft:blocks/*</code>, 箱子战利品表 <code>minecraft:chests/*</code>和游戏内容(钓鱼、猪灵以物换物、村民礼物、猫的礼物) <code>minecraft:gameplay/*</code>。</p>


<h2 id="战利品表谓词">§2.6 战利品表谓词</h2>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/predicates/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/战利品表谓词" class="wiki">战利品表谓词</a></li>
  <li><a href="https://minecraft.wiki/w/Predicate" class="wikien">Predicate</a></li>
  <li><a href="https://www.mcbbs.net/thread-914817-1-4.html">【CBL|SPG】[1.16] Predicate —— 数据包的组成文件之一</a></li>
</ul>

<p>战利品表谓词 (Predicate) 用于对所在情形进行条件判断，可作为战利品表的条件、命令 <code>execute</code> 的条件子命令 <code>(if|unless) predicate foo:bar</code>、目标选择器参数 <code>predicate={foo:bar}</code>、<a href="#进度">进度</a>中判断实体条件等。<a href="#战利品表">战利品表</a>的条件和战利品表谓词格式相同。</p>
<p>注意1.17和旧版本的物品谓词和方块谓词有差异。</p>
<pre class="file" id="战利品表谓词JSON格式">战利品表谓词JSON格式</pre>
<pre><span class="comment">我们省略了部分信息的格式，请自行前往 wiki 查阅。</span>
{
  "condition": "minecraft:alternative",<span class="comment">下述任一条件满足时通过</span>
  "terms": [
    <a href="#战利品表条件JSON对象">战利品表条件JSON对象</a>1,
    <a href="#战利品表条件JSON对象">战利品表条件JSON对象</a>2
  ]
}

{
  "condition": "minecraft:inverted",<span class="comment">下述条件不满足时通过</span>
  "term": <a href="#战利品表条件JSON对象">战利品表条件JSON对象</a>
}

{
  "condition": "minecraft:reference",<span class="comment">引用其它的战利品表谓词，注意避免循环引用</span>
  "name": "战利品表谓词命名空间ID"
}

{
  "condition": "minecraft:random_chance",<span class="comment">以一定概率通过，通过几率为 chance</span>
  "chance": 数值
}

{
  "condition": "minecraft:random_chance",<span class="comment">以一定概率通过，通过几率为 chance+looting_multiplier×抢夺等级</span>
  "chance": 数值,
  "looting_multiplier": 数值 <span class="comment">若并非 entity 类型战利品表该项会被忽略</span>
}

{
  "condition": "minecraft:survives_explosion",<span class="comment">block 类型战利品表若方块是被爆炸破坏的，该条件有 1/爆炸半径 的几率通过。其它情形永远通过。</span>
}

{
  "condition": "minecraft:location_check",<span class="comment">检查死亡的实体位置/方块位置/命令执行位置。注意该条件用在方块掉落物战利品表时，方块已经被挖掘掉，因此该位置方块总是空气。</span>
  "offsetX": 数值, <span class="comment">可选，默认为0，X轴偏移量</span>
  "offsetY": 数值, <span class="comment">可选，默认为0，Y轴偏移量</span>
  "offsetZ": 数值, <span class="comment">可选，默认为0，Z轴偏移量</span>
  "predicate": 位置信息共通标签  <span class="comment">检查偏移后的位置</span>
}

{
  "condition": "minecraft:time_check",<span class="comment">检测当前游戏内的时间</span>
  "value": <a href="#范围谓词">范围谓词</a>,
  "period": 数值 <span class="comment">可选，判断前先对该数值取模</span>
}

{
  "condition": "minecraft:weather_check",<span class="comment">检测当前游戏内的天气</span>
  "raining": "true" 或 "false", <span class="comment">可选，是否正在下雨(含雷雨天)</span>
  "thundering": "true" 或 "false", <span class="comment">可选，是否正在打雷</span>
}

{
  "condition": "minecraft:value_check",<span class="comment">检测 value 是否位于 range 范围内</span>
  "value": <a href="#值提供器">值提供器</a>,
  "range": <a href="#值提供器">值提供器</a>
  或 {
    "min": <a href="#值提供器">值提供器</a>,
    "max": <a href="#值提供器">值提供器</a>
  }
}

<span class="comment">下述战利品表谓词仅对 block 或 fishing 类型战利品表可用。</span>
{
  "condition": "minecraft:match_tool",<span class="comment">检查挖掘/钓鱼的工具</span>
  "predicate": 物品共通标签
}

{
  "condition": "minecraft:block_state_property",<span class="comment">检查方块。该条件用在方块掉落物战利品表时，不能被 location_check 替代，因为后者进行判断时方块已经被挖掘掉，其位置总是空气。</span>
  "terms": [
    "block": "方块命名空间ID",
    "properties": {
      "方块状态名": "字符串" 或 布尔值 或 <a href="#范围谓词">范围谓词</a>
    }
  ]
}

{
  "condition": "minecraft:table_bonus",<span class="comment">定义不同级别的附魔等级下条件的通过几率</span>
  "enchantment": "魔咒命名空间ID", <span class="comment">探测的魔咒</span>
  "chances": [
    数值, <span class="comment">没有该魔咒时的通过几率</span>
    数值, <span class="comment">该魔咒为1级时的通过几率</span>
    数值, <span class="comment">该魔咒为2级时的通过几率</span>
    ...
    数值 <span class="comment">该魔咒为至少n级时的通过几率</span>
  ]
}

<span class="comment">下述战利品表谓词仅对 entity 或 generic 类型战利品表可用。</span>
{
  "condition": "minecraft:damage_source_properties",<span class="comment">检查当前伤害</span>
  "predicate": 伤害类型共通标签
}

{
  "condition": "minecraft:killed_by_player",<span class="comment">判断击杀者是否为玩家</span>
  "inverted": "true" (默认) 或 "false" <span class="comment">可选，true 时当击杀者是玩家时通过，false 时当击杀者不是玩家时通过。</span>
}

<span class="comment">下述战利品表谓词仅对 entity 或 generic 类型战利品表以及命令可用。</span>
{
  "condition": "minecraft:entity_properties",<span class="comment">检查实体</span>
  "entity": "this" <span class="comment">死亡的实体或命令执行者</span>或 "killer" <span class="comment">击杀者</span>或 "player_killer", <span class="comment">击杀目标的玩家</span>
  "scores": {
    "记分板名称1": <a href="#范围谓词">范围谓词</a>,
    "记分板名称2": <a href="#范围谓词">范围谓词</a>
  }
}

{
  "condition": "minecraft:entity_scores",<span class="comment">检查实体记分板</span>
  "entity": "this" 或 "killer" 或 "player_killer", <span class="comment">含义同上</span>
  "predicate": 实体共通标签
}
</pre>

<pre class="file" id="范围谓词">范围谓词</pre>
<pre>
  数值
或
  {
    "min": 数值, <span class="comment">可选, 最小值</span>
    "max": 数值, <span class="comment">可选, 最大值</span>
  }
</pre>

<p>这个例子表示玩家的分数 <code>cppChainTick</code> 至少为 <code>1</code> 时，或者手持物具有特定标签时通过。</p>
<pre class="file">cpp/predicates/chain_effect.json</pre>
<pre>{
  "condition": "minecraft:alternative",
  "terms": [
    {
      "condition": "minecraft:entity_scores",
      "entity": "this",
      "scores": {
        "cppChainTick": {
          "min": 1
        }
      }
    },
    {
      "condition": "minecraft:entity_properties",
      "entity": "this",
      "predicate": {
        "equipment": {
          "mainhand": {
            "nbt": "{cppStoredEffects:[{id:\"chain\"}]}"
          }
        }
      }
    }
  ]
}</pre>

<p>战利品表谓词文件也可以为战利品表谓词JSON对象的列表。这个例子表示玩家的手持物或盔甲拥有指定标签，且玩家不拥有 <code>cpp:temperancer</code> 时通过。</p>
<pre class="file">cpp/predicates/stored_effects</pre>
<pre>[
  {
    "condition": "minecraft:alternative",
    "terms": [
      {
        "condition": "minecraft:entity_properties",
        "entity": "this",
        "predicate": {
          "equipment": {
            "mainhand": {
              "nbt": "{cppStoredEffects:[{}]}"
            }
          }
        }
      },
      {
        "condition": "minecraft:entity_properties",
        "entity": "this",
        "predicate": {
          "equipment": {
            "head": {
              "nbt": "{cppStoredEffects:[{}]}"
            }
          }
        }
      },
      {
        "condition": "minecraft:entity_properties",
        "entity": "this",
        "predicate": {
          "equipment": {
            "chest": {
              "nbt": "{cppStoredEffects:[{}]}"
            }
          }
        }
      },
      {
        "condition": "minecraft:entity_properties",
        "entity": "this",
        "predicate": {
          "equipment": {
            "legs": {
              "nbt": "{cppStoredEffects:[{}]}"
            }
          }
        }
      },
      {
        "condition": "minecraft:entity_properties",
        "entity": "this",
        "predicate": {
          "equipment": {
            "feet": {
              "nbt": "{cppStoredEffects:[{}]}"
            }
          }
        }
      }
    ]
  },
  {
    "condition": "minecraft:inverted",
    "term": {
      "condition": "minecraft:entity_properties",
      "entity": "this",
      "predicate": {
        "nbt": "{Inventory:[{tag:{id:\"cpp:temperancer\"}}]}"
      }
    }
  }
]</pre>


<h2 id="物品修饰器">§2.7 物品修饰器</h2>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/item_modifiers/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/物品修饰器" class="wiki">物品修饰器</a></li>
  <li><a href="https://minecraft.wiki/w/Item_modifier" class="wikien">Item modifier</a></li>
  <li><a href="https://www.mcbbs.net/thread-914817-1-4.html">【CBL|SPG】[1.16] Predicate —— 数据包的组成文件之一</a></li>
</ul>

<p>物品修饰器 (Item modifier) 用于在<a href="https://zh.minecraft.wiki/w/命令/item">命令</a> <code>/item</code> 中对物品添加战利品表函数。<a href="#战利品表">战利品表</a>的函数和物品修饰器格式相同，但物品修饰器不可被战利品表的函数引用。</p>

<pre class="file" id="物品修饰器JSON格式">物品修饰器JSON格式</pre>
<pre>
<span class="comment">修改物品数量的函数，最终不会超过该物品的最大可堆叠数。</span>
{
  "function": "minecraft:set_count", <span class="comment">设置数量</span>
  "count": <a href="#值提供器">值提供器</a>,
  "add": true 或 false <span class="comment">将count加到原本的数量中，还是设置数量为count</span>
}

{
  "function": "minecraft:apply_bonus",<span class="comment">指定物品数量服从与特定魔咒等级有关的分布</span>
  "enchantment": "魔咒命名空间ID",<span class="comment">检查该魔咒的等级</span>
  "formula": "binomial_with_bonus_count", <span class="comment">使用参数为 n=魔咒等级+extra 和 p=probability 的二项分布。</span>
  "parameters": {
    "extra": 整数,
    "probability": 数值
  }
或
  "formula": "uniform_bonus_count", <span class="comment">使用0至 魔咒等级×bonusMultiplier 的均匀分布。</span>
  "parameters": {
    "bonusMultiplier": 数值
  }
或
  "formula": "ore_drops", <span class="comment">使用矿物默认掉落数的分布，即有1/(魔咒等级+2)几率为之前的函数已设定的数量×(2至(魔咒等级+1))，有2/(魔咒等级+2)几率为之前的函数已设定的数量。</span>
}

{
  "function": "minecraft:limit_count", <span class="comment">限制每一种物品的堆叠数量，即其它函数得到的物品堆叠数量如果超过这个值，会被设定为该值</span>
  "limit": <a href="#值提供器">值提供器</a> <span class="comment">限制堆叠数量</span>
        或 {
          "min": <a href="#值提供器">值提供器</a>, <span class="comment">限制堆叠数量最小值</span>
          "min": <a href="#值提供器">值提供器</a> <span class="comment">限制堆叠数量最大值</span>
        }
}

{
  "function": "minecraft:looting_enchant", <span class="comment">抢夺魔咒会额外增加物品数量 等级×count</span>
  "count": <a href="#值提供器">值提供器</a>,
  "limit": 数值 <span class="comment">可选，默认为0无限制。限制最终数量的上限</span>
}

{
  "function": "minecraft:explosion_decay" <span class="comment">仅用于 block 类型战利品表，当目标方块被爆炸摧毁时，执行该函数的每个物品有1/爆炸半径的几率消失，堆叠的物品会被分为多个单独的物品计算。</span>
}

<span class="comment">下列函数可以改变物品NBT。</span>
{
  "function": "minecraft:copy_name", <span class="comment">将方块实体的 CustomName 标签复制到物品的 display.Name 标签。仅用于 block 类型战利品表</span>
  "source": "block_entity"
}

{
  "function": "minecraft:copy_state",<span class="comment">复制方块的方块状态到物品的BlockStateTag标签。仅用于 block 类型战利品表</span>
  "block": 方块命名空间ID,<span class="comment">仅当目标方块与该ID相符时执行该函数</span>
  "properties": [<span class="comment">要复制的方块状态列表</span>
    "字符串"
  ]
}

{
  "function": "minecraft:copy_nbt", <span class="comment">复制NBT到物品的tag标签</span>
  "source": "block_entity" <span class="comment">来源为被破坏的方块，仅用于 block 类型战利品表</span>
          或
            "this" <span class="comment">命令执行者；entity 类型战利品表的死亡者；进度奖励中获得进度的玩家；block 类型战利品表的打开或破坏容器的玩家</span>
          或
            "killer" <span class="comment">entity 类型战利品表的击杀者</span>
          或
            "killer_player" <span class="comment">entity 类型战利品表的击杀者，必须是玩家</span>
          或
            {
              "type": "context",
              "target": "this" 或 "killer" 或 "direct_killer" 或 "player_killer" <span class="comment">和前面的写法等价</span>
            或
              "type": "storage", <span class="comment">设置来源为命令存储空间(storage)</span>
              "source": "命令存储空间的命名空间ID"
            },
  "ops": [
    {
      "source": "字符串", <span class="comment">要被复制的NBT路径</span>
      "target": "字符串", <span class="comment">要复制到的NBT路径，从物品的tag标签开始</span>
      "op": "replace" <span class="comment">替换目标的所有存在的内容</span>
          或
            "append" <span class="comment">追加到一个列表</span>
          或
            "merge" <span class="comment">融合到一个复合标签</span>
    }
  ]
}

{
  "function": "minecraft:set_name", <span class="comment">设置物品自定义名称，该函数可以对JSON文本中组件进行解析。</span>
  "name"："<a href="https://zh.minecraft.wiki/w/原始JSON文本格式">原始JSON文本</a>",
  "entity": <span class="comment">指定JSON文本里中@s表示的实体</span> "this" <span class="comment">命令执行者；entity 类型战利品表的死亡者；进度奖励中获得进度的玩家；block 类型战利品表的打开或破坏容器的玩家</span>
  或
    "killer" <span class="comment">entity 类型战利品表的击杀者</span>
  或
    "killer_player" <span class="comment">entity 类型战利品表的击杀者，必须是玩家</span>
}

{
  "function": "minecraft:set_lore", <span class="comment">设置物品附加文本(lore)标签，该函数可以对JSON文本中组件进行解析。</span>
  "lore"：[
    "<a href="https://zh.minecraft.wiki/w/原始JSON文本格式">原始JSON文本1</a>",
    "<a href="https://zh.minecraft.wiki/w/原始JSON文本格式">原始JSON文本2</a>"
  ],
  "entity": <span class="comment">指定JSON文本里中@s表示的实体</span> "this" <span class="comment">命令执行者；entity 类型战利品表的死亡者；进度奖励中获得进度的玩家；block 类型战利品表的打开或破坏容器的玩家</span>
  或
    "killer" <span class="comment">entity 类型战利品表的击杀者</span>
  或
    "killer_player", <span class="comment">entity 类型战利品表的击杀者，必须是玩家</span>
  "replace": true 或 false <span class="comment">如果为true，则替换物品当前的lore；如果为false，则在物品lore后追加内容。</span>
}

{
  "function": "minecraft:set_nbt", <span class="comment">为物品添加NBT标签</span>
  "tag": "NBT对象" <span class="comment">添加NBT标签，和命令的使用方法类似。注意最外层括号需要书写花括号（{}）以及内部的引号需要使用转义符（\）标记。</span>
}

{
  "function": "minecraft:set_stew_effect", <span class="comment">为迷之炖菜添加状态效果</span>
  "effects": [
    {
      "type"："<a href="#https://zh.minecraft.wiki/w/状态效果/ID">状态效果命名空间ID</a>"
      "duration"：<a href="#值提供器">值提供器</a> <span class="comment">指定状态效果的持续时间</span>
    }
  ]
}

{
  "function": "minecraft:enchant_randomly", <span class="comment">为物品附上一个随机的魔咒。魔咒的等级也是随机的。</span>
  "enchantments"：[ <span class="comment">能够附上的魔咒列表。如果没有此标签，所有可以对该物品附上的魔咒都可能被附上。</span>
    "魔咒命名空间ID1",
    "魔咒命名空间ID2"
  ]
}

{
  "function": "minecraft:enchant_with_levels", <span class="comment">使用指定的附魔等级附魔物品</span>
  "treasure": true 或 false, <span class="comment">该物品是否能被附上宝藏魔咒</span>
  "levels": <a href="#值提供器">值提供器</a> <span class="comment">指定该附魔的等级，超过99会无效。</span>
}

{
  "function": "minecraft:set_enchantments‌", <span class="comment">设置物品附魔</span>
  "enchantments": {
    "魔咒命名空间ID": <a href="#值提供器">值提供器</a>, <span class="comment">该魔咒的等级</span>
  },
  "add": true 或 false <span class="comment">追加魔咒还是覆盖原有魔咒</span>
}

{
  "function": "minecraft:fill_player_head", <span class="comment">给玩家头颅添加指定物品标签</span>
  "entity": "this" <span class="comment">命令执行者；entity 类型战利品表的死亡者；进度奖励中获得进度的玩家；block 类型战利品表的打开或破坏容器的玩家</span>
          或
            "killer" <span class="comment">entity 类型战利品表的击杀者</span>
          或
            "killer_player" <span class="comment">entity 类型战利品表的击杀者，必须是玩家</span>
}

{
  "function": "minecraft:set_attributes", <span class="comment">为物品加上属性修饰符</span>
  "modifiers": [<span class="comment">属性修饰符列表</span>
    {
      "name": "字符串", <span class="comment">修改器的名称</span>
      "attribute": "字符串", <span class="comment">此修改器修改的<a href="https://zh.minecraft.wiki/w/属性">属性</a>的名称</span>
      "operation": "addition" 或 "multiply_base" 或 "multiply_total", <span class="comment">修改数值的方法</span>
      "amount": <a href="#值提供器">值提供器</a> <span class="comment">要修改的数值</span>
      或 {
        "min": <a href="#值提供器">值提供器</a>, <span class="comment">要修改的数值最小值</span>
        "min": <a href="#值提供器">值提供器</a> <span class="comment">要修改的数值最大值</span>
      },
      "id": "字符串", <span class="comment">可选，修改器的UUID。如果没有指定，则生成新的UUID。不建议手动指定。</span>
      "slot": "mainhand" 或 "offhand" 或 "feet" 或 "legs" 或 "chest" 或 "head" <span class="comment">该属性生效的栏位</span>
          或
            [ <span class="comment">随机选择列表中的一个栏位</span>
              "栏位1",
              "栏位2",
            ]
    }
  ]
}

{
  "function": "minecraft:set_banner_pattern‌", <span class="comment">设置旗帜样式</span>
  "patterns": [
    {
      "pattern": "base" 或 "border" 或 "bricks" 或 "circle" 或 "creeper" 或 "cross" 或 "curly_border" 或 "diagonal_left" 或 "diagonal_right" 或 "diagonal_up_left" 或 "diagonal_up_right" 或 "flower" 或 "globe" 或 "gradient" 或 "gradient_up" 或 "half_horizontal" 或 "half_horizontal_bottom" 或 "half_vertical" 或 "half_vertical_right" 或 "mojang" 或 "piglin" 或 "rhombus" 或 "skull" 或 "small_stripes" 或 "square_bottom_left" 或 "sqaure_bottom_right" 或 "square_top_left" 或 "square_top_right" 或 "straight_cross" 或 "stripe_bottom" 或 "stripe_center" 或 "stripe_downleft" 或 "stripe_downright" 或 "stripe_left" 或 "stripe_middle" 或 "stripe_right" 或 "stripe_top" 或 "triangle_bottom" 或 "triangle_top" 或 "triangles_bottom" 或 "triangles_top", <span class="comment">旗帜样式</span>
      "color": "white" 或 "orange" 或 "magenta" 或 "light_blue" 或 "yellow" 或 "lime" 或 "pink" 或 "gray" 或 "light_gray" 或 "cyan" 或 "purple" 或 "blue" 或 "brown" 或 "green" 或 "red" 或 "black <span class="comment">该样式的颜色</span>
    }
  ],
  "append": true 或 false <span class="comment">是否是追加到旗帜已有的样式上，若否则覆盖之</span>
}

{
  "function": "minecraft:set_damage", <span class="comment">设置物品耐久</span>
  "damage": <a href="#值提供器">值提供器</a>, <span class="comment">物品已损伤的比例</span>
  "add": true 或 false <span class="comment">是否相对于当前耐久来设置</span>
}

{
  "function": "minecraft:set_loot_table", <span class="comment">设置容器物品的战利品表</span>
  "type": 方块命名空间ID, <span class="comment">只允许是方块实体</span>
  "name": "<a href="#战利品表">战利品表</a>命名空间ID",
  "seed": 数值 <span class="comment">战利品表种子，可选。默认为0，不指定种子。</span>
}

<span class="comment">下列函数可以改变物品ID。</span>
{
  "function": "minecraft:furnace_smelt" <span class="comment">物品将变为在熔炉里烧炼后的状态。支持数据包添加的熔炉烧炼配方，但不支持高炉、烟熏炉或营火的烧炼配方。</span>
}

{
  "function": "minecraft:exploration_map", <span class="comment">将普通的地图物品变为一个指引到某个结构的探险家地图</span>
  "destination": "结构类型", <span class="comment">理论上应该和<a href="https://zh.minecraft.wiki/w/命令/locate#参数">/locate命令中的参数</a>一样，实际上每个单词都需要首字母大写。</span>
  "decoration": "<a href="https://zh.minecraft.wiki/w/地图#地图图标">地图图标ID</a>", <span class="comment">该结构在地图中显示的图标（大小写敏感）。如果设置为mansion或monument，地图物品的图标将会改变。</span>
  "zoom": 整数, <span class="comment">默认为2。地图缩放等级</span>
  "search_radius": 整数, <span class="comment">默认为50。搜寻以当前区块为中心的(search_radius+1)×(search_radius+1)的区块。</span>
  "skip_existing_chunks": true(默认值) 或 false <span class="comment">是否在搜寻时跳过已生成的区块</span>
}

{
  "function": "minecraft:set_contents", <span class="comment">指定掉落物为容器时其内含物，仅对容器的方块战利品表有效</span>
  "type": 方块命名空间ID, <span class="comment">只允许是方块实体</span>
  "entries": [ 
    战利品表项目列表 <span class="comment">设置为dynamic类型的content，可使容器保留其内含物。但除潜影盒外的容器被破坏时总会将内含物掉出。</span>
  ]
}

</pre>
<p>物品修饰器也可以为物品修饰器JSON对象的列表。例如下例中我们提前将需要设置的耐久存入 <code>storage cpp:_</code> 的 <code>Damage</code>，且已损伤的耐久不小于 <code>25</code> 时将其数量-1。</p>
<pre class="file" id="cpp/item_modifiers/chest_transporter">cpp/item_modifiers/chest_transporter.json</pre>
<pre>
[
  {
    "function": "minecraft:copy_nbt",
    "source": {
      "type": "storage",
      "source": "cpp:_"
    },
    "ops": [
      {
        "op": "replace",
        "source": "tag.Damage",
        "target": "Damage"
      }
    ]
  },
  {
    "conditions": [
      {
        "condition": "minecraft:value_check",
        "range": {
          "min": 25
        },
        "value": {
          "type": "minecraft:score",
          "target": {
            "type": "minecraft:fixed",
            "name": "#damage"
          },
          "score": "cppValue"
        }
      }
    ],
    "function": "minecraft:set_count",
    "add": false,
    "count": 0
  }
]
</pre>
<p>例：将玩家1个副手物品移动到头盔栏。注意引用时应当先检测玩家头盔栏是否为空再执行该函数。</p>
<pre class="file" id="cpp/item_modifiers/one">cpp/item_modifiers/one.json</pre>
<pre>
{
  "function": "set_count",
  "count": 1,
  "add": false
}
</pre>
<pre class="file" id="cpp/item_modifiers/minus">cpp/item_modifiers/minus.json</pre>
<pre>
{
  "function": "set_count",
  "count": -1,
  "add": true
}
</pre>
<pre class="file" id="cpp/functions/hat">cpp:hat</pre>
<pre>
item entity @s armor.head copy entity @s weapon.offhand cpp:one
# 注意有的物品不能放置在头盔栏，此时不应当将副手物品数量-1
execute if data entity @s Inventory[{Slot:103b}] run item entity @s weapon.offhand modify <a href="#cpp/item_modifiers/minus">cpp:minus</a>
</pre>

<p>例：获取函数执行者手持物的最大耐久。</p>
<pre class="file" id="cpp/functions/get_durality">cpp:get_durality</pre>
<pre>
setblock ~ 255 ~ barrel
item block ~ 255 ~ container.0 copy entity @s weapon.mainhand cpp:set_damage
execute store result score #max_durality cppValue run data get block ~ 255 ~ Items[0].tag.Damage
setblock ~ 255 ~ air
</pre>
<pre class="file" id="cpp/item_modifiers/set_damage">cpp/item_modifiers/set_damage.json</pre>
<pre>
{
  "function": "minecraft:set_damage",
  "add": false,
  "damage": 0
}
</pre>

<h2 id="配方">§2.8 配方</h2>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/recipes/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/配方" class="wiki">配方</a></li>
  <li><a href="https://minecraft.wiki/w/Recipe" class="wikien">Recipe</a></li>
</ul>

<p>配方 (Recipe) 为游戏内指定工作台合成、切石机合成、熔炉烧炼、高炉烧炼、烟熏炉烧炼、营火烧炼和锻造台合成的格式，一般<strong>不支持带 NBT 标签</strong>。</p>
<p>在默认情形(限制配方关闭)下，玩家总是可以使用所有的配方，且使用一个配方会使玩家自动发现它。因此建议为你的自定义配方添加合适的进度来获取该配方。一旦配方被发现，就将被加入玩家的配方书。配方只会在玩家使用与当前配方类型所匹配的方块时显示。例如，烧炼配方将只在熔炉的界面中显示。当在背包中使用配方书时，只有能在玩家的 <code>2×2</code> 背包合成栏内使用的配方才会显示。已发现的配方储存在玩家 <code>recipeBook</code> 的NBT中。 </p>
<p>原版的合成、烧炼使用配方文件即可实现，较为简单，但是无法识别且无视配方材料的NBT(除了特殊合成配方)，因此只能实现原版物品的合成和烧炼。同时原版模组若使用了相关物品，则相应的模组物品亦可代替原物品进行合成。想要实现带NBT的合成需要藉由其它方式，见<a href="#NBT合成与烧炼">NBT合成与烧炼</a>。</p>
<p>锻造台则会保留要升级的物品的NBT信息而只修改其id。</p>

<p>大部分配方中所使用的配方材料格式可以为下述几种。</p>
<pre class="file" id="配方材料">配方材料JSON格式</pre>
<pre>
{
  "item": "物品命名空间ID" <span class="comment">相应物品</span>
}
或
{
  "tag": "<a href="#物品标签">物品标签</a>命名空间ID" <span class="comment">物品标签中的任一物品</span>
}
或
[ <span class="comment">列表中任一对象的物品</span>
  配方材料JSON对象
]
</pre>

<h3 id="有序合成">§2.8.1 有序合成</h3>
<pre class="file" id="有序合成/JSON格式">JSON格式</pre>
<pre>
{
  "group": "字符串", <span class="comment">可选，具有相同该标识符的配方会在配方书中显示为一组。</span>
  "type": "minecraft:crafting_shaped", <span class="comment">表示有序合成</span>
  "pattern": [ <span class="comment">由单字符键所组成的数组，用于描述配方的图案。至多3个字符串，每个字符串长度一致且至多为3。空格代表一个空的合成栏位。</span>
    "###", 
    "#A#",
    "###"
  ],
  "key": { <span class="comment">所有该有序合成配方用到的键。</span>
    "A": <a href="#配方材料">配方材料</a>JSON对象 或 <a href="#配方材料">配方材料</a>JSON对象列表,
    "#": <a href="#配方材料">配方材料</a>JSON对象 或 <a href="#配方材料">配方材料</a>JSON对象列表,
  },
  "result": {
    "item": "物品命名空间ID", <span class="comment">输出的物品</span>
    "count": 正整数 <span class="comment">可选，输出的物品数量，默认为1</span>
  }
}
</pre>

<p class="ex">使用6羊毛+鸡蛋工字形有序合成两个羊刷怪蛋。</p>
<pre class="file" id="cpp/recipes/sheep_spawn_egg">cpp/recipes/sheep_spawn_egg.json</pre>
<pre>
{
  "type": "minecraft:crafting_shaped",
  "pattern": [
    "WWW",
    " E ",
    "WWW"
  ],
  "key": {
    "E": {
      "item": "minecraft:egg"
    },
    "W": {
      "tag": "cpp:wools"
    }
  },
  "result": {
    "item": "minecraft:sheep_spawn_egg",
    "count":2
  }
}
</pre>
<p class="noindent">这里 <code>cpp:wools</code> 为自定义的包含所有颜色羊毛的物品标签。</p>

<h3 id="无序合成">§2.8.2 无序合成</h3>

<pre class="file" id="无序合成/JSON格式">JSON格式</pre>
<pre>
{
  "group": "字符串", <span class="comment">可选，具有相同该标识符的配方会在配方书中显示为一组。</span>
  "type": "minecraft:crafting_shapeless", <span class="comment">表示无序合成</span>
  "ingredients": [ <span class="comment">配方材料列表，该无序合成配方的一系列原料，数量应在1至9个之间。 </span>
    <a href="#配方材料">配方材料</a>JSON对象 或 <a href="#配方材料">配方材料</a>JSON对象列表
  ],
  "result": {
    "item": "物品命名空间ID", <span class="comment">输出的物品</span>
    "count": 正整数 <span class="comment">可选，输出的物品数量，默认为1</span>
  }
}
</pre>
<p>配料可以重复。单个物品配方请使用有序合成而不是无序合成。</p>

<p class="ex">2沙子和红石无序合成2红沙。</p>
<pre class="file" id="cpp/recipes/red_sand">cpp/recipes/red_sand.json</pre>
<pre>
{
  "type": "minecraft:crafting_shapeless",
  "ingredients": [
    {
      "item": "minecraft:sand"
    },
    {
      "item": "minecraft:sand"
    },
    {
      "item": "minecraft:redstone"
    }
  ],
  "result": {
    "item": "minecraft:red_sand",
    "count":2
  }
}
</pre>

<h3 id="切石机配方">§2.8.3 切石机配方</h3>

<pre class="file" id="切石机配方/JSON格式">JSON格式</pre>
<pre>
{
  "group": "字符串", <span class="comment">可选，具有相同该标识符的配方会在配方书中显示为一组。</span>
  "type": "minecraft:stonecutting", <span class="comment">表示切石机配方</span>
  "ingredients": <a href="#配方材料">配方材料</a>JSON对象 或 <a href="#配方材料">配方材料</a>JSON对象列表,
  "result": {
    "item": "物品命名空间ID", <span class="comment">输出的物品</span>
    "count": 正整数 <span class="comment">输出的物品数量，默认为1</span>
  }
}
</pre>
<p>注意 <code>result.count</code> 不能省略。</p>

<p class="ex">使用切石机切割橡木木板为2台阶。</p>
<pre class="file" id="cpp/recipes/stonecutting/oak_slab">cpp/recipes/stonecutting/oak_slab.json</pre>
<pre>
{
  "type": "minecraft:stonecutting",
  "ingredient": {
    "item": "minecraft:oak_planks"
  },
  "result": "minecraft:oak_slab",
  "count": 2
}
</pre>

<h3 id="烧炼配方">§2.8.4 烧炼配方</h3>
<pre class="file" id="烧炼配方/JSON格式">JSON格式</pre>
<pre>
{
  "group": "字符串", <span class="comment">可选，具有相同该标识符的配方会在配方书中显示为一组。</span>
  "type": "minecraft:smelting"<span class="comment">表示熔炉配方</span> 或 "minecraft:blasting"<span class="comment">表示高炉配方</span> 或 "minecraft:smoking"<span class="comment">表示烟熏炉配方</span> 或 "minecraft:campfire_cooking"<span class="comment">表示营火配方</span>,
  "ingredients": <a href="#配方材料">配方材料</a>JSON对象 或 <a href="#配方材料">配方材料</a>JSON对象列表,
  "result": "物品命名空间ID", <span class="comment">输出的物品</span>,
  "experience": 数值, <span class="comment">该配方产生的经验值</span>
  "cookingtime": 正整数 <span class="comment">可选，该配方的烧炼时间，单位：刻。如果缺省，将使用默认的时间。</span>
}
</pre>
<p>熔炉配方的默认烧炼时间是200刻，即10秒。高炉配方和烟熏炉配方的默认烧炼时间是100刻，即5秒。营火的默认烧炼时间是100刻，即5秒，但所有的原版营火配方都将烧炼时间修改为了600刻，即30秒。</p>

<p class="ex">熔炉烧炼皮革装备、腐肉、鞍为兔子皮。</p>
<pre class="file" id="cpp/recipes/rabbit_hide_from_smelting">cpp/recipes/rabbit_hide_from_smelting.json</pre>
<pre>
{
  "type": "minecraft:smelting",
  "ingredient": [
    {
      "item": "minecraft:rotten_flesh"
    },
    {
      "item": "minecraft:leather_helmet"
    },
    {
      "item": "minecraft:leather_chestplate"
    },
    {
      "item": "minecraft:leather_leggings"
    },
    {
      "item": "minecraft:leather_boots"
    },
    {
      "item": "minecraft:saddle"
    }
  ],
  "result": "minecraft:rabbit_hide",
  "experience": 0.1,
  "cookingtime": 200
}
</pre>

<h3 id="锻造台配方">§2.8.5 锻造台配方</h3>
<pre class="file" id="锻造台配方/JSON格式">JSON格式</pre>
<pre>
{
  "group": "字符串", <span class="comment">可选，具有相同该标识符的配方会在配方书中显示为一组。</span>
  "type": "minecraft:smithing", <span class="comment">表示锻造台配方</span>
  "base": <a href="#配方材料">配方材料</a>JSON对象, <span class="comment">指定一个要升级的物品</span>
  "addition": <a href="#配方材料">配方材料</a>JSON对象, <span class="comment">升级所需的消耗品</span>
  "result": "物品命名空间ID" <span class="comment">升级得到的物品</span>
}
</pre>

<p class="ex">使用锻造台使用钻石将铁斧升级为钻石斧。</p>
<pre class="file" id="cpp/recipes/smithing/diamond_axe">cpp/recipes/smithing/diamond_axe.json</pre>
<pre>
{
  "type": "minecraft:smithing",
  "base": {
    "item": "minecraft:iron_axe"
  },
  "addition": {
    "item": "minecraft:diamond"
  },
  "result": {
    "item": "minecraft:diamond_axe"
  }
}
</pre>

<h3 id="工作台特殊配方">§2.8.6 工作台特殊配方</h3>
<p>工作台有一些特殊配方由游戏内部的代码处理，无法通过JSON文件来修改。这些配方均涉及物品的NBT修改。当<a href="#原版数据包">原版数据包</a>被禁用时，你可以用它们来重新启用你所需要的特殊合成配方。 </p>
<pre class="file" id="工作台特殊配方/JSON格式">JSON格式</pre>
<pre>
{
  "type": "minecraft:crafting_special_armordye" <span class="comment">盔甲染色配方</span>
或
  "type": "minecraft:crafting_special_bannerduplicate" <span class="comment">旗帜复制配方</span>
或
  "type": "minecraft:crafting_special_bookcloning" <span class="comment">成书复制配方</span>
或
  "type": "minecraft:crafting_special_firework_rocket" <span class="comment">使用烟火之星合成烟花火箭的配方</span>
或
  "type": "minecraft:crafting_special_firework_star" <span class="comment">烟火之星的合成配方</span>
或
  "type": "minecraft:crafting_special_firework_star_fade" <span class="comment">烟火之星的色彩淡化配方</span>
或
  "type": "minecraft:crafting_special_mapcloning" <span class="comment">地图复制配方</span>
或
  "type": "minecraft:crafting_special_mapextending" <span class="comment">地图比例缩小配方</span>
或
  "type": "minecraft:crafting_special_repairitem" <span class="comment">物品修复配方</span>
或
  "type": "minecraft:crafting_special_shielddecoration" <span class="comment">给盾牌添加图案的配方</span>
或
  "type": "minecraft:crafting_special_shulkerboxcoloring" <span class="comment">潜影盒染色配方</span>
或
  "type": "minecraft:crafting_special_tippedarrow" <span class="comment">药箭配方</span>
或
  "type": "minecraft:crafting_special_suspiciousstew" <span class="comment">迷之炖菜配方</span>
}
</pre>


<h3 id="覆盖原版配方">§2.8.7 覆盖原版配方</h3>
<p>在数据包的<code>pack.mcmeta</code>中可以指定忽略的数据包文件，例如下面就屏蔽了原版棕色蘑菇合成兔肉煲的配方，以及用于解锁该配方的相应进度。</p>
<pre class="file">pack.mcmeta</pre>
<pre>
{
  "pack": {
    "pack_format": 10
  },
  "filter": {
    "block": [
      {
        "namespace": "minecraft",
        "path": "recipes/rabbit_stew_from_brown_mushroom.json"
      },
      {
        "namespace": "minecraft",
        "path": "advancements/recipes/food/rabbit_stew_from_brown_mushroom.json"
      }
    ]
  }
}
</pre>
<p>1.19之前的版本如果想要修改原版的合成或烧炼配方，先使用压缩软件打开版本 <code>.jar</code> 文件，依次打开 <code>data/minecraft/recipes</code>，找到相应的配方文件，然后在自己的数据包中的相同位置（必然是 <code>minecraft</code> 命名空间下）放入同名文件即可覆盖默认的配方。</p>
<p class="ex">将橡木台阶合成数量改为8。</p>

<pre class="file" id="minecraft/recipes/oak_stairs">minecraft/recipes/oak_stairs.json</pre>
<pre>
{
  "type": "minecraft:crafting_shaped",
  "group": "wooden_stairs",
  "pattern": [
    "#  ",
    "## ",
    "###"
  ],
  "key": {
    "#": {
      "item": "minecraft:oak_planks"
    }
  },
  "result": {
    "item": "minecraft:oak_stairs",
    "count": 8
  }
}
</pre>
<p class="ex">将原版白色床+墨囊=黑色床的合成配方修改为任意床+墨囊=黑色床。</p>

<pre class="file" id="cpp/tags/items/beds">cpp/tags/items/beds.json</pre>
<pre>
{
  "replace": false,
  "values": [
    "minecraft:white_bed",
    "minecraft:orange_bed",
    "minecraft:magenta_bed",
    "minecraft:light_blue_bed",
    "minecraft:yellow_bed",
    "minecraft:lime_bed",
    "minecraft:pink_bed",
    "minecraft:gray_bed",
    "minecraft:light_gray_bed",
    "minecraft:cyan_bed",
    "minecraft:purple_bed",
    "minecraft:blue_bed",
    "minecraft:brown_bed",
    "minecraft:green_bed",
    "minecraft:red_bed",
    "minecraft:black_bed"
  ]
}
</pre>
<pre class="file" id="minecraft/recipes/black_bed_from_white_bed">minecraft/recipes/black_bed_from_white_bed.json</pre>
<pre>
{
  "type": "crafting_shapeless",
  "group": "dyed_bed",
  "ingredients": [
    {
      "tag": "cpp:beds"
    },
    {
      "item": "minecraft:black_dye"
    }
  ],
  "result": {
    "item": "minecraft:black_bed"
  }
}
</pre>
<p>如果需要删除原版配方，可使用生存无法获得的方块如基岩=基岩、屏障=屏障、结构空位等物品来合成。配方文件内容为 <code>{}</code> 时会被认为是错误文件而无法覆盖原配方。同时，我们需要将解锁该配方的进度触发器设置为 <code>minecraft:impossible</code>。</p>

<h3 id="配方获取">§2.8.8 配方获取</h3>
<p>一个完整的配方应当有相应的进度来使玩家获取之，通常触发器为玩家背包含有合成材料。也可以根据需要在函数中使用命令 <code>recipe</code> 给予。</p>

<pre class="file" id="cpp/advancements/recipes/dirt_from_cobblestone_snowball">cpp/advancements/recipes/dirt_from_cobblestone_snowball.json</pre>
<pre>
{
  "criteria": {
    "cobblestone": {
      "trigger": "minecraft:inventory_changed",
      "conditions": {
        "items": [
          {
            "items": ["minecraft:cobblestone"],
            "count": {
              "min": 8
            }
          }
        ]
      }
    },
    "snowball": {
      "trigger": "minecraft:inventory_changed",
      "conditions": {
        "items": [
          {
            "items": ["minecraft:snowball"]
          }
        ]
      }
    },
    "has_the_recipe": {
      "trigger": "minecraft:recipe_unlocked",
      "conditions": {
        "recipe": "cpp:dirt_from_cobblestone_snowball"
      }
    }
  },
  "rewards":{
    "recipes": ["cpp:dirt_from_cobblestone_snowball"]
  },
  "requirements": [
    [
      "cobblestone",
      "snowball",
      "has_the_recipe"
    ]
  ]
}
</pre>


<h2 id="结构">§2.9 结构</h2>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/structures/<i>路径</i>/<i>文件名</i>.nbt</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/结构方块" class="wiki">结构方块</a></li>
  <li><a href="https://minecraft.wiki/w/Structure_Block" class="wikien">Structure Block</a></li>
  <li><a href="http://www.mcbbs.net/thread-652937-1-1.html">建筑党也能愉快享用结构方块-图文并茂教会你使用结构方块</a></li>
  <li><a href="http://www.mcbbs.net/thread-801350-1-1.html">如何使用结构方块</a></li>
</ul>

<p>结构 (Structure) 存储了一个长方体区域的方块和实体信息，玩家可以使用结构方块来创建、保存、调用结构。结构大小一般至多为 <code>48×48×48</code>，1.15及更早版本则至多为 <code>32×32×32</code>。</p>
<p>在游戏中获得结构方块后，放置好所需要的方块结构和实体，然后放置结构方块，设置为保存模式，调整好大小，输入名称（命名空间ID），点保存即可（注意区分是否需要保存实体）。然后从 <code>.minecraft/saves/<i>世界名称</i>/generated/<i>命名空间</i>/structures/<i>路径</i>/<i>文件名</i>.nbt</code> 复制到数据包内。调用时，在结构方块中输入命名空间ID来加载（注意区分是否需要加载实体）。</p>
<p>我们也可以在函数中加载，先放置结构方块，然后放置并清除红石块，最后清除结构方块。这个技巧配合战利品表和断言，可用于随机在世界生成结构，也可直接用于<a href="#模板池">模板池</a>。例如：</p>
<pre class="file" id="cpp/functions/generate/enchanting_room.mcfunction">cpp/functions/generate/enchanting_room.mcfunction</pre>
<pre>
setblock ~ ~ ~ structure_block{posX:-1,posY:0,posZ:-1,name:"cpp:build/enchanting_room",mode:"LOAD"}
setblock ~ ~1 ~ redstone_block
setblock ~ ~1 ~ air
</pre>
<p>结构文件的NBT结构为：</p>
<ul>
  <li>size 结构的长宽高；</li>
  <li>entities 结构包含的实体；</li>
  <li>blocks 结构包含的方块，其中 pos 指定了相对坐标，state 指定了该方块在方块状态列表的编号，从0开始；</li>
  <li>palette 方块状态列表，其中 Name 为方块命名空间ID，Properties 指定该方块的所有方块状态。也可以为palettes，这个列表的每一个项目都是一个方块状态列表，然后调用结构时会根据种子(坐标和完整度)来确定选择哪一个列表来使用，原版的沉船就使用该方式来存储。</li>
</ul>
<p>通过直接编辑结构文件，我们可以绕过使用结构方块保存的一些限制。在游戏内保存好大致的结构后，使用NBT编辑器打开：</p>
<ul>
  <li>通过直接修改结构的<code>palettes</code>，可以将设置随机的结构方块状态列表；</li>
  <li>通过直接修改结构的<code>size</code>，可以将结构设置为大于48的区域；</li>
  <li>通过修改<code>blocks</code>的<code>pos</code>，我们可以指定长方体区域外位置的方块；</li>
  <li>通过修改<code>entities</code>，我们可以删除实体不需要保存的一些NBT，这通常包括<code>Air, FallDistance, Fire, Motion, NoGravity, OnGround, PortalCooldown, Pos, Rotation, UUID</code>等，<code>blockPos</code>也可以删除。</li>
</ul>
<p>这些技巧的使用请参考<a href="#任意纯方块结构">任意纯方块结构</a>。</p>
<p>如果结构用于<a href="#结构地物">结构地物</a>中，当结构只有部分在已加载区块中时，系统会根据结构的<code>size</code>来确定还有哪些部分没有被加载。<code>blocks</code>的<code>pos</code>不在长方体区域内，这可能会导致生成的结构不完整。</p>

<h2 id="标签">§2.10 标签</h2>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/标签" class="wiki">标签</a></li>
  <li><a href="https://minecraft.wiki/w/Tag" class="wikien">Tag</a></li>
</ul>

<p>标签 (Tag) 用于将多个具有相同性质的内容放置在一起以便于调用。Minecraft 中有很多内容都叫做标签，注意区分它们。</p>
<pre class="file" id="标签/JSON格式">标签JSON格式</pre>
<pre>
{
  "replace": true 或 false (默认值), <span class="comment">可选，true 表示覆盖之前原版和其它数据包中该标签的内容，false 表示追加当前内容至该标签</span>
  "values": [ <span class="comment">字符串或JSON对象的列表</span>
    "minecraft:stone", <span class="comment">可以为相应类别的"命名空间ID"</span>
    "#cpp:logs", <span class="comment">可以为相应类别标签的"#命名空间ID"</span>
    {
      "id": "minecraft:dirt", <span class="comment">相应类别的"命名空间ID"或标签的"#命名空间ID"</span>
      "required": true 或 false, <span class="comment">false 表示该条目是可选的，解析可选条目失败不会影响其它条目的加载</span>
    }
  ]
}
</pre>
<p>由于数据包加载次序难以控制，因此 <code>"replace": true</code> 的情形较为少用，一般仅用于覆盖原版标签。</p>
<p>标签的 <code>required</code> 设置为 false 时，可用于添加其他模组的相应ID。这在为数据包添加对模组的支持时很有用，例如<a href="#cpp/tags/blocks/chests">cpp/tags/blocks/chests.json</a>。而函数标签则为数据包添加附属和扩展提供了方便的接口。</p>
<p>标签共包括6种，分别用于不同情形。</p>

<h3 id="方块标签">§2.10.1 方块标签</h3>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/tags/blocks/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<p>方块标签 (Block tag) 可以在用命令测试方块时以 <code>#<i>命名空间ID</i></code> 的格式调用，只要方块满足了该标签中定义的任何一个方块，命令就会测试通过。方块标签还可在进度、断言、战利品表中以 <code>"tag": "<i>命名空间ID</i>"</code> 的格式调用。调试模式(F3)下，玩家指向方块时会显示含有该方块的所有方块标签。</p>

<p>原版方块标签被用于各种方块属性，我们按照功能分类并列出。我们不列出仅用于其它标签、进度、断言、战利品表、影响生物寻路和影响方块连接的方块标签。</p>
<table><thead><tr><th>方块标签</th><th>用途</th></tr></thead><tbody>
<tr><td><code>minecraft:enderman_holdableats</code></td><td>末影人可以捡起这些方块</td></tr>
<tr><td><code>minecraft:dragon_immune</code></td><td>末影龙无法破坏这些方块</td></tr>
<tr><td><code>minecraft:wither_immune</code></td><td>凋灵无法破坏这些方块</td></tr>
<tr><td><code>minecraft:wither_summon_base_blocks</code></td><td>可以用来搭建凋灵的方块</td></tr>
<tr><td><code>minecraft:hoglin_repellents</code></td><td>疣猪兽会远离这些方块</td></tr>
<tr><td><code>minecraft:logs</code></td><td>鹦鹉可以在这些方块上栖息<br/>影响周围树叶方块的方块状态 <code>distance</code><br/>树生长时可以替代这些方块</td></tr>
<tr><td><code>minecraft:strider_warm_blocks</code></td><td>炽足兽不在这些方块当中时会打寒颤</td></tr>
<tr><td><code>minecraft:guarded_by_piglins</code></td><td>玩家破坏这些方块会激怒附近的猪灵，不影响打开会激怒猪灵的方块</td></tr>
<tr><td><code>minecraft:piglin_repellents</code></td><td>猪灵会避开这些方块</td></tr>
<tr><td><code>minecraft:flowers</code></td><td>蜜蜂可以授粉并记住这些方块的位置<br/>邻近的树苗生长后有几率带有蜂巢</td></tr>
<tr><td><code>minecraft:bee_growables</code></td><td>当蜜蜂对这些植物进行授粉时，它们会生长一个阶段，从该标签中删除方块没有效果</td></tr>
<tr><td><code>minecraft:beehives</code></td><td>如果将蜂巢或蜂箱移除，则蜜蜂不再会为它们填充蜂蜜，用带有玻璃瓶或剪刀的发射器也不会清除其中的蜂蜜</td></tr>
<tr><td><code>minecraft:campfires</code></td><td>蜜蜂、鹦鹉和海龟会尝试避开<br/>营火使用这个标签来确定它们是否可被打火石点燃<br/>喷溅型水瓶可将其方块状态变为 <code>lit=false</code></td></tr>
<tr><td><code>minecraft:sand</code></td><td>海龟蛋可以在这些方块上孵化</td></tr>
<tr><td><code>minecraft:beds</code></td><td>猫可以坐或睡在这些方块上<br/>村民可以睡在这些方块上<br/>幼年村民可以跳到这些方块上</td></tr>
<tr><td><code>minecraft:prevent_mob_spawning_inside</code></td><td>生物不能在这些方块里生成</td></tr>

<tr><td><code>minecraft:valid_spawn</code></td><td>用于确定位置是否是玩家的有效出生位置</td></tr>
<tr><td><code>minecraft:climbable</code></td><td>玩家进入该方块时是否可以攀爬</td></tr>
<tr><td><code>minecraft:soul_speed_blocks</code></td><td>穿着附有灵魂疾行魔咒的靴子在这些方块上的行走速度会得到提高</td></tr>
<tr><td><code>minecraft:wool</code></td><td>这些方块可以被使用剪刀以5倍的速度破坏<br/>放在这些方块上的音符盒会发出吉他音效</td></tr>
<tr><td><code>minecraft:leaves</code></td><td>这些方块将剪刀识别为正确的工具，使用剑摧毁时速度是正常情况下的1.5倍，使用剪刀破坏的速度是正常情况下的15倍<br/>不阻碍任何地形特征的生成<br/>用于确定某些方块的是否可以放置其上<br/>鹦鹉和豹猫可以在这些方块中生成</td></tr>
<tr><td><code>minecraft:portals</code></td><td>当骑着一个实体的实体从其上脱离时，它将不会落在在这些方块中以防止不需要的传送，而是会脱离在被骑乘的实体的位置</td></tr>
<tr><td><code>minecraft:rails</code></td><td>检测是否与铁轨相连。矿车是否可在此方块上行驶。检测是否可以放置矿车。向此标签添加其他方块会导致游戏崩溃。TNT矿车位于这些方块内时，不会破坏所在位置的方块和下方的方块。</td></tr>
<tr><td><code>minecraft:fences</code></td><td>可以将拴绳连接到这些方块</td></tr>
<tr><td><code>minecraft:anvil</code></td><td>如果将原版三种铁砧移除，则它们不再可以打开GUI<br/>该标签包含的铁砧的下落方块形式、以及其它方块的使用命令召唤的下落方块形式，可以伤害实体</td></tr>

<tr><td><code>minecraft:underwater_bonemeals</code></td><td>当在暖洋生物群系中在水下使用骨粉时，该标签中的方块将取代水源方块（在5个水平块和2个垂直块内）。如果该标记中的方块是自定义的，则该行为将应用于任何生物群系中的水源方块。这些方块在默认情况下不会含水</td></tr>
<tr><td><code>minecraft:jungle_logs</code></td><td>可可豆可种植在这些方块上</td></tr>
<tr><td><code>minecraft:beacon_base_blocks</code></td><td>可用于信标基座</td></tr>
<tr><td><code>minecraft:bamboo_plantable_on</code></td><td>竹子可种植在该方块上</td></tr>
<tr><td><code>minecraft:mushroom_grow_block‌</code></td><td>其之上的蘑菇可以无视光照放下且可以被骨粉催熟为巨型蘑菇</td></tr>
<tr><td><code>minecraft:soul_fire_base_blocks</code></td><td>灵魂火会在这些方块上燃烧</td></tr>
<tr><td><code>minecraft:wall_post_override</code></td><td>会使方块下方的墙变成柱子</td></tr>
<tr><td><code>minecraft:fire</code></td><td>不影响且可用于激活有效的未激活下界传送门<br/>不会阻挡沙子等方块掉落<br/>能够扑灭火焰的药水会移除这些方块</td></tr>

<tr><td><code>minecraft:saplings</code></td><td>树生长时可以替代这些方块</td></tr>
<tr><td><code>minecraft:base_stone_overworld‌</code></td><td>生成世界时，主世界地下的石头中的点缀(砂砾堆、泥土堆、石头变种堆、矿脉、被虫蚀的方块)可以生成在这些方块的位置</td></tr>
<tr><td><code>minecraft:base_stone_nether‌</code></td><td>生成世界时，下界的远古残骸可以生成在这些方块的位置</td></tr>
<tr><td><code>minecraft:corals</code></td><td>用于生成珊瑚礁</td></tr>
<tr><td><code>minecraft:coral_blocks</code></td><td>用于生成珊瑚礁<br/>对着该方块顶部的单个海泡菜使用骨粉会使其生长出更多的海泡菜</td></tr>

<tr><td><code>minecraft:infiniburn_overworld</code></td><td><a href="#维度类型">维度类型</a>为 minecraft:overworld 的维度中火焰可在这些方块上永久燃烧</td></tr>
<tr><td><code>minecraft:infiniburn_nether</code></td><td><a href="#维度类型">维度类型</a>为 minecraft:the_nether 的维度中火焰可在这些方块上永久燃烧</td></tr>
<tr><td><code>minecraft:infiniburn_end</code></td><td><a href="#维度类型">维度类型</a>为 minecraft:the_end 的维度中火焰可在这些方块上永久燃烧</td></tr>

<tr><td><code>minecraft:impermeable</code></td><td>流体和蜂蜜颗粒不会穿过这些方块</td></tr>


</tbody></table>

<p class="ex">检测玩家头部是否被方块卡住。</p>
<pre class="file" id="cpp/tags/blocks/fluid">cpp/tags/blocks/fluid.json</pre>
<pre>
{
  "replace": false,
  "values": [
    "minecraft:air",
    "minecraft:cave_air",
    "minecraft:void_air",
    "minecraft:bubble_column",
    "minecraft:water",
    "minecraft:lava",
    "#minecraft:fire"
  ]
}
</pre>
<p class="noindent">然后执行命令</p>
<pre class="file" id="cpp/functions/check.mcfunction">cpp/functions/check.mcfunction</pre>
<pre>
execute unless block ^ ^ ^ #cpp:fluid
</pre>
<p class="noindent">因为命令执行地点为实体的脚，所以我们使用 <code>anchored eyes</code> 来使得局部坐标的位置变为玩家的眼睛。</p>

<p class="ex">让末影人无法拿起任何方块。</p>
<pre class="file" id="minecraft/tags/blocks/enderman_holdable">minecraft/tags/blocks/enderman_holdable</pre>
<pre>
{
  "replace": true,
  "values": [
  ]
}
</pre>

<h3 id="物品标签">§2.10.2 物品标签</h3>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/tags/items/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<p>物品标签 (Item tag) 在配方、进度、断言、战利品表中用 <code>"tag": "<i>命名空间ID</i>"</code> 的格式使用。还可在创造模式物品栏输入 <code>#<i>命名空间ID</i></code> 来搜索相应标签物品。物品标签命名空间ID<code>命名空间:路径/文件名</code>对应的文件为 <code>命名空间/tags/items/路径/文件名.json</code>。</p>

<p>原版物品标签被用于各种物品属性，我们按照功能分类并列出。我们不列出仅用于其它标签、配方、进度、断言、战利品表，影响生物寻路和影响方块连接的物品标签。</p>

<table><thead><tr><th>物品标签</th><th>用途</th></tr></thead><tbody>
<tr><td><code>minecraft:boats</code></td><td>这些物品可以放入熔炉的燃料槽，并重置燃烧时间为 <code>1200</code> 刻</td></tr>
<tr><td><code>minecraft:banners</code></td><td rowspan="7">这些物品可以放入熔炉的燃料槽，并重置燃烧时间为 <code>300</code> 刻</td></tr>
<tr><td><code>minecraft:logs</code></td></tr>
<tr><td><code>minecraft:planks</code></td></tr>
<tr><td><code>minecraft:wooden_pressure_plates</code></td></tr>
<tr><td><code>minecraft:wooden_stairs</code></td></tr>
<tr><td><code>minecraft:wooden_trapdoors</code></td></tr>
<tr><td><code>minecraft:wooden_buttons</code></td></tr>
<tr><td><code>minecraft:signs</code></td><td rowspan="2">这些物品可以放入熔炉的燃料槽，并重置燃烧时间为 <code>200</code> 刻</td></tr>
<tr><td><code>minecraft:wooden_doors</code></td></tr>
<tr><td><code>minecraft:wooden_slabs</code></td><td>这些物品可以放入熔炉的燃料槽，并重置燃烧时间为 <code>150</code> 刻</td></tr>
<tr><td><code>minecraft:saplings</code></td><td rowspan="2">这些物品可以放入熔炉的燃料槽，并重置燃烧时间为 <code>100</code> 刻</td></tr>
<tr><td><code>minecraft:wool</code></td></tr>
<tr><td><code>minecraft:carpets</code></td><td>这些物品可以放入熔炉的燃料槽，并重置燃烧时间为 <code>67</code> 刻</td></tr>
<tr><td><code>minecraft:non_flammable_wood</code></td><td>这些物品不能被用作熔炉的燃料</td></tr>

<tr><td><code>minecraft:piglin_loved</code></td><td>成年猪灵会捡起这些物品</td></tr>
<tr><td><code>minecraft:piglin_repellents</code></td><td>猪灵不会捡起这些物品</td></tr>
<tr><td><code>minecraft:flowers</code></td><td>这些物品可以用来繁殖蜜蜂</td></tr>
<tr><td><code>minecraft:small_flowers</code></td><td>这些物品可用于喂食棕色哞菇<br/>移除会使其不能用于合成迷之炖菜</td></tr>
<tr><td><code>minecraft:fishes</code></td><td>海豚会游向持有这些物品的玩家，用它们喂养海豚会使海豚“信任”你</td></tr>
<tr><td><code>minecraft:creeper_drop_music_discs</code></td><td>苦力怕被骷髅杀死后可以掉落的物品</td></tr>

<tr><td><code>minecraft:arrows</code></td><td>这些物品可以像箭一样被射出和捡起</td></tr>

<tr><td><code>minecraft:beacon_payment_items</code></td><td>这些物品可以放置在信标GUI中以选择效果</td></tr>
<tr><td><code>minecraft:planks</code></td><td>这些物品可以在铁砧中修复木质工具和盾牌</td></tr>
</tbody></table>

<p class="ex">让纸可以作为熔炉燃料使用，每次可烧炼一个物品。</p>
<pre class="file" id="minecraft/tags/items/wooden_doors">minecraft/tags/items/wooden_doors</pre>
<pre>
{
  "replace": false,
  "values": [
    "minecraft:paper"
  ]
}
</pre>

<h3 id="函数标签">§2.10.3 函数标签</h3>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/tags/functions/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<p>函数标签 (Function tag) 可以在 <code>function</code> 命令中以 <code>#<i>命名空间ID</i></code> 的形式调用，所有在该标签中指定的函数都会按照它们出现的顺序执行，不会重复执行。函数标签命名空间ID<code>命名空间:路径/文件名</code>对应的文件为 <code>命名空间/tags/functions/路径/文件名.json</code>。</p>
<p><code>minecraft</code> 命名空间中的标签</p>
<ul>
  <li><code>minecraft/tags/functions/load.json</code> 中的函数会在加载时被执行一次，我们常称之为加载函数、load函数。用于初始化的函数应当添加至该标签。</li>
  <li><code>minecraft/tags/functions/tick.json</code> 中的函数每刻会被执行一次，我们常称之为循环函数、主函数、tick函数。需要高频执行的函数应当添加至该标签。</li>
</ul>
<p>本文中我们有时会不加注明地使用<code><i>命名空间</i>:load</code> 和<code><i>命名空间</i>:tick</code> 表示这两个函数标签中的函数。</p>

<h3 id="实体类型标签">§2.10.4 实体类型标签</h3>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/tags/entity_types/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<p>实体类型标签 (Entity type tag) 标签可以在实体选择器参数 <code>type</code> 以及战利品表条件中以 <code>#<i>命名空间ID</i></code> 的形式调用，只要实体满足了该标签中定义的任何一个类型，就会被选中。实体类型标签命名空间ID<code>命名空间:路径/文件名</code>对应的文件为 <code>命名空间/tags/entity_types/路径/文件名.json</code>。</p>
<p>原版实体类型标签被用于各种实体属性，我们在此列出。</p>

<table><thead><tr><th>物品标签</th><th>用途</th></tr></thead><tbody>
<tr><td><code>arrows</code></td><td>使用在瞄准目标进度中</td></tr>
<tr><td><code>beehive_inhabitors</code></td><td>这些实体可以进入蜂箱。</td></tr>
<tr><td><code>impact_projectiles</code></td><td>用来决定哪些实体可以击破紫颂果，只有标靶方块可以响应的实体才有效</td></tr>
<tr><td><code>raiders</code></td><td>决定敲钟时哪些实体获得发光效果，此标签中的实体在骑乘劫掠兽时不会覆盖劫掠兽的AI</td></tr>
<tr><td><code>skeletons</code></td><td>苦力怕在被这些实体杀死时掉落唱片</td></tr>
</tbody></table>

<h3 id="流体标签">§2.10.5 流体标签</h3>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/tags/fluids/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<p>流体标签 (Fluid tag) 标签很少使用，修改后会影响空气、水和熔岩的性质，其命名空间ID<code>命名空间:路径/文件名</code>对应的文件为 <code>命名空间/tags/fluids/路径/文件名.json</code>。</p>
<p>流体和流体对应的方块是不同的，例如 <code>flowing_water</code> 不是一个合法的方块，但流体可以为</p>
<pre>
{
  "minecraft:water",
  "minecraft:flowing_water",
  "minecraft:lava",
  "minecraft:flowing_lava",
  "minecraft:air",
  "minecraft:cave_air",
  "minecraft:void_air"
}
</pre>
<p>原版流体标签 <code>minecraft:water</code> 和 <code>minecraft:lava</code> 用来决定何种流体具有类似水和熔岩的性质，具体见<a href="https://zh.minecraft.wiki/w/标签#流体" class="wiki">标签#流体</a>，我们在此省略。</p>

<h3 id="游戏事件标签">§2.10.6 游戏事件标签</h3>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/tags/game_events/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<p> 游戏事件标签 (Game event tag) 标签目前仅用于指定影响潜声传感器的事件，其命名空间ID<code>命名空间:路径/文件名</code>对应的文件为 <code>命名空间/tags/game_events/路径/文件名.json</code>。</p>
<p>原版游戏事件标签 <code>minecraft:vibrations</code> 用于决定哪些事件会被潜声传感器检测到，<code>minecraft:ignore_vibrations_stepping_carefully</code> 用于决定哪些事件在玩家潜行时不会被潜声传感器检测到，具体见<a href="https://zh.minecraft.wiki/w/%E6%A0%87%E7%AD%BE#.E6.B8.B8.E6.88.8F.E4.BA.8B.E4.BB.B6.E2.90.8C.5B.E6.96.B0.E5.A2.10E.EF.BC.9AJE_1.17.5D" class="wiki">标签#游戏事件</a>。</p>

<h2 id="维度和维度类型">§2.11 维度和维度类型</h2>

<p>维度和维度类型用于自定义维度。维度和自定义世界生成无法通过命令 <code>/reload</code> 在游戏内更新。</p>

<h3 id="维度">§2.11.1 维度</h3>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/dimension/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/自定义维度" class="wiki">自定义维度</a></li>
  <li><a href="https://minecraft.wiki/w/Custom_dimension" class="wikien">Custom dimension</a></li>
  <li><a href="https://www.bilibili.com/video/BV1z5411a7rH">EP1. 维度与维度类型</a></li>
  <li><a href="https://www.bilibili.com/video/BV1Gt4y1D7Wx">EP2. 多噪声生物群系源</a></li>
</ul>

<p>维度 (Dimension) 规定了维度的生成方式和生物群系。</p>

<p>噪声型维度的的地形由<a href="#噪声设置">噪声设置</a> <code>generator.settings</code> 确定，生物群系由 <code>generator.biome_source</code> 的不同可分为五种情形，其中类型为 <code>multi_noise</code> 时，游戏会生成四维柏林噪声图，然后对每个坐标选择噪声最接近的生物群系。其中生物群系的 <code>offset</code> 会影响计算接近程度，从而影响该生物群系的大小，<code>offset</code> 越大，该生物群系越难被选中。</p>

<pre class="file" id="噪声型维度JSON格式">噪声型维度JSON格式</pre>
<pre>
{
  "type": "<a href="#维度类型">维度类型</a>命名空间ID" 或 <a href="#维度类型">维度类型</a>JSON对象,
  "generator": {
    "type"："minecraft:noise",
    "seed"：整数, <span class="comment">种子</span>
    "settings"："<a href="#噪声设置">噪声设置</a>命名空间ID" 或 <a href="#噪声设置">噪声设置</a>JSON对象,
    "biome_source": { <span class="comment">生物群系设置</span>
      "seed"：整数, <span class="comment">种子</span>

      "type": "minecraft:vanilla_layered", <span class="comment">原主世界默认生成和巨型生物群系生成</span>
      "large_biomes": true 或 false, <span class="comment">是否为巨型生物群系</span>
    或
      "type": "minecraft:multi_noise", <span class="comment">多维噪声型</span>
      "min_quart_y": 整数, <span class="comment">TBD</span>
      "max_quart_y": 整数, <span class="comment">TBD</span>
      "biomes": [ <span class="comment">生物群系列表</span>
        {
          "biome": "<a href="#生物群系">生物群系</a>命名空间ID", <span class="comment">生物群系</span>
          "parameters": { <span class="comment">生物群系属性</span>
            "humidity": -2~2 之间的数值范围, <span class="comment">振幅，柏林噪声参数</span>
            "erosion": -2~2 之间的数值范围, <span class="comment">振幅，柏林噪声参数</span>
            "temperature": -2~2 之间的数值范围, <span class="comment">振幅，柏林噪声参数</span>
            "weirdness": -2~2 之间的数值范围, <span class="comment">振幅，柏林噪声参数</span>
            "continentalness": -2~2 之间的数值范围, <span class="comment">振幅，柏林噪声参数</span>
            "depth": 数值, <span class="comment">TBD</span>
            "offset": 0~1 之间的数值 <span class="comment">为地图上的点计算最接近的生物群系时，会根据这个值来调大距离，因此这个值绝对值越大，生物群系越小</span>
          }
        }
      ]
    或
      "type": "minecraft:fixed", <span class="comment">单生物群系维度</span>
      "biome": "<a href="#生物群系">生物群系</a>命名空间ID"
    或
      "type": "minecraft:checkerboard", <span class="comment">生物群系单元呈正方形按棋盘状排列</span>
      "scale": 正整数, <span class="comment">正方形单元的大小</span>
      "biomes": [ <span class="comment">生物群系列表</span>
        "<a href="#生物群系">生物群系</a>命名空间ID"
      ]
    或
      "type": "minecraft:the_end" <span class="comment">用于在末路之地中生成的生物群系，以生物群系minecraft:the_end为中心，周围环绕着其它生物群系</span>
    }
  }
}
</pre>

<p id="超平坦型维度">超平坦型维度仅需指定方块层的分布、生物群系和使用的结构参数即可。如果生成要塞，则要塞由原点向外逐个生成在一系列的环上，直到总数达到 <code>count</code>。其中第 <code>i</code> 个环的要塞数量为 <code>spread × (i+1) × (i+2)/6</code> 向下取整，第 <code>i</code> 个环到原点的平均距离为 <code>distance × (6i-2)</code> 个区块。</p>
<pre class="file" id="超平坦型维度JSON格式">超平坦型维度JSON格式</pre>
<pre>
{
  "type": "<a href="#维度类型">维度类型</a>命名空间ID" 或 <a href="#维度类型">维度类型</a>JSON对象,
  "generator": {
    "type": "minecraft:flat",
    "settings": {
      "layers": [
        {
          "height": 正整数, <span class="comment">该层方块高度</span>
          "block": "方块命名空间ID" <span class="comment">该层使用方块</span>
        }
      ],
      "biome": "<a href="#生物群系">生物群系</a>命名空间ID", <span class="comment">该维度使用的单一生物群系</span>
      "lakes": true 或 false, <span class="comment">可选，是否生成湖。如果设为true，则水湖和熔岩湖常会生成，即使在生物群系中湖通常不生成。熔岩湖生成时会被主世界不同种类的石头和矿物包围</span>
      "features": true 或 false, <span class="comment">可选，是否生成生物群系特有的装饰性结构，比如主世界的树木、花、草、仙人掌，下界的火/灵魂火、菌类、菌索等等</span>
      "structures": { <span class="comment">结构设置</span>
        "stronghold": { <span class="comment">可选，要塞的生成设置</span>
          "count": 1~4095 之间的整数,
          "spread": 0~1023 之间的整数, <span class="comment">设置为0时会使世界中某些位置上反复生成多个要塞</span>
          "distance": 0~1023 之间的整数
        },
        "structures": { <span class="comment">该维度中会生成的结构，如果需要生成要塞也需在此列出</span>
          "<a href="https://zh.minecraft.wiki/w/Java版数据值#结构">结构</a>命名空间ID": { <span class="comment">注意这不是<a href="#结构地物">结构地物</a>命名空间ID，自定义的结构地物生成几率设置随同其对应的原版结构</span>
            "spacing": 正整数, <span class="comment">两个该种类的结构之间的平均距离，以区块为单位</span>
            "separation": 1~(spacing-1) 之间的整数, <span class="comment">两个该种类的结构之间的最小距离，以区块为单位</span>
            "salt": 整数 <span class="comment">影响结构内部生成</span>
          }
        }
      }
    }
  }
}
</pre>
<p>调试世界维度仅用于调试世界，没有其它可选的设置。</p>
<pre class="file" id="调试世界维度JSON格式">调试世界维度JSON格式</pre>
<pre>
{
  "type": "<a href="#维度类型">维度类型</a>命名空间ID" 或 <a href="#维度类型">维度类型</a>JSON对象,
  "generator": {
    "type": "minecraft:debug"
  }
}
</pre>

<p>原版的维度包括</p>
<pre class="file"><a href="vanilla/data/minecraft/dimension/overworld.json">minecraft:overworld</a></pre>
<pre>
{
  "type": "<a href="#minecraft/dimension_type/overworld">minecraft:overworld</a>",
  "generator": {
    "biome_source": {
      "seed": 0,
      "large_biomes": false,
      "type": "minecraft:vanilla_layered"
    },
    "seed": 0,
    "settings": "<a href="#minecraft/worldgen/noise_settings/overworld">minecraft:overworld</a>",
    "type": "minecraft:noise"
  }
}
</pre>
<pre class="file"><a href="vanilla/data/minecraft/dimension/the_nether.json">minecraft:the_nether</a></pre>
<pre>
{
  "type": "<a href="#minecraft/dimension_type/the_nether">minecraft:the_nether</a>",
  "generator": {
    "biome_source": {
      "humidity_noise": {
        "firstOctave": -7,
        "amplitudes": [
          1.0,
          1.0
        ]
      },
      "altitude_noise": {
        "firstOctave": -7,
        "amplitudes": [
          1.0,
          1.0
        ]
      },
      "weirdness_noise": {
        "firstOctave": -7,
        "amplitudes": [
          1.0,
          1.0
        ]
      },
      "seed": 0,
      "biomes": [
        {
          "parameters": {
            "altitude": 0.0,
            "weirdness": 0.0,
            "offset": 0.0,
            "temperature": 0.0,
            "humidity": 0.0
          },
          "biome": "minecraft:nether_wastes"
        },
        {
          "parameters": {
            "altitude": 0.0,
            "weirdness": 0.0,
            "offset": 0.0,
            "temperature": 0.0,
            "humidity": -0.5
          },
          "biome": "minecraft:soul_sand_valley"
        },
        {
          "parameters": {
            "altitude": 0.0,
            "weirdness": 0.0,
            "offset": 0.0,
            "temperature": 0.4,
            "humidity": 0.0
          },
          "biome": "minecraft:crimson_forest"
        },
        {
          "parameters": {
            "altitude": 0.0,
            "weirdness": 0.0,
            "offset": 0.375,
            "temperature": 0.0,
            "humidity": 0.5
          },
          "biome": "minecraft:warped_forest"
        },
        {
          "parameters": {
            "altitude": 0.0,
            "weirdness": 0.0,
            "offset": 0.175,
            "temperature": -0.5,
            "humidity": 0.0
          },
          "biome": "minecraft:basalt_deltas"
        }
      ],
      "temperature_noise": {
        "firstOctave": -7,
        "amplitudes": [
          1.0,
          1.0
        ]
      },
      "type": "minecraft:multi_noise"
    },
    "seed": 0,
    "settings": "<a href="#minecraft/worldgen/noise_settings/overworld">minecraft:nether</a>",
    "type": "minecraft:noise"
  }
}
</pre>
<pre class="file"><a href="vanilla/data/minecraft/dimension/the_end.json">minecraft:the_end</a></pre>
<pre>
{
  "type": "<a href="#minecraft/dimension_type/the_end">minecraft:the_end</a>",
  "generator": {
    "biome_source": {
      "seed": 0,
      "type": "minecraft:the_end"
    },
    "seed": 0,
    "settings": "<a href="#minecraft/worldgen/noise_settings/overworld">minecraft:end</a>",
    "type": "minecraft:noise"
  }
}
</pre>

<h3 id="维度类型">§2.11.2 维度类型</h3>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/dimension_type/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/自定义维度#维度类型" class="wiki">维度类型</a></li>
  <li><a href="https://minecraft.wiki/w/Custom_dimension#Dimension_type" class="wikien">Dimension type</a></li>
</ul>

<p>维度类型 (Dimension type) 规定维度的一些与地形无关的信息。</p>

<pre class="file" id="维度类型JSON格式">维度类型JSON格式</pre>
<pre>
{
  "has_ceiling": true 或 false, <span class="comment">该维度是否拥有一个基岩天花板，影响内部的算法，与实际是否拥有基岩天花板无关</span>
  "logical_height": 数值, <span class="comment">玩家使用紫颂果或下界传送门可以到达的最大高度</span>
  "bed_works": true 或 false, <span class="comment">玩家是否可以使用床</span>
  "respawn_anchor_works": true 或 false, <span class="comment">玩家是否可以使用重生锚</span>
  "has_raids": true 或 false, <span class="comment">带有不祥之兆的玩家是否可以触发袭击</span>
  "has_skylight": true 或 false, <span class="comment">该维度是否有天空光照</span>
  "ambient_light": 0~1 之间的数值, <span class="comment">该维度拥有多少环境光</span>
  "natural": true 或 false, <span class="comment">当为 false 时，指南针会随机转动；当为 true 时，下界传送门会生成僵尸猪灵</span>
  "piglin_safe：true 或 false, <span class="comment">猪灵和疣猪兽是否不会僵尸化</span>
  "coordinate_scale": 数值, <span class="comment">当前维度坐标放缩倍率，影响下界传送门和 execute in 指令使用相对坐标/局部坐标的情形</span>
  "ultrawarm": true 或 false, <span class="comment">维度是否表现得类似于下界水会蒸发，湿海绵会干。这也会使得熔岩流动更快、扩散更远</span>
  "fixed_time": 0~24000 之间的整数, <span class="comment">可选，游戏内的昼夜时间固定值, 缺省则有日夜循环</span>
  "min_y": 数值, <span class="comment">此维度中可以存在方块的最低高度</span>
  "height": 不超过4096的16的倍数, <span class="comment">此维度中可以存在方块的总高度。维度中可以存在方块的最大高度的值等于min_y与height值之和</span>
  "infiniburn": "<a href="#方块标签">方块标签</a>命名空间ID" <span class="comment">决定该维度中火可以在什么方块上永久燃烧</span>
}
</pre>

<h4 id="可用的维度类型">可用的维度类型</h4>
<p>这些是 Minecraft 内部已生成的维度类型命名空间ID，可直接使用。已省略 minecraft:。</p>
<pre class="file" id="minecraft/dimension_type/overworld"><a href="vanilla/data/minecraft/dimension_type/overworld.json">minecraft:overworld</a></pre>
<pre>
{
  "logical_height": 256,
  "infiniburn": "minecraft:infiniburn_overworld",
  "effects": "minecraft:overworld",
  "ambient_light": 0.0,
  "respawn_anchor_works": false,
  "has_raids": true,
  "min_y": 0,
  "height": 256,
  "natural": true,
  "coordinate_scale": 1.0,
  "piglin_safe": false,
  "bed_works": true,
  "has_skylight": true,
  "has_ceiling": false,
  "ultrawarm": false
}
</pre>
<pre class="file" id="minecraft/dimension_type/overworld_caves"><a href="vanilla/data/minecraft/dimension_type/overworld_caves.json">minecraft:overworld_caves</a></pre>
<pre>
{
  "logical_height": 256,
  "infiniburn": "minecraft:infiniburn_overworld",
  "effects": "minecraft:overworld",
  "ambient_light": 0.0,
  "respawn_anchor_works": false,
  "has_raids": true,
  "min_y": 0,
  "height": 256,
  "natural": true,
  "coordinate_scale": 1.0,
  "piglin_safe": false,
  "bed_works": true,
  "has_skylight": true,
  "has_ceiling": true,
  "ultrawarm": false
}
</pre>

<pre class="file" id="minecraft/dimension_type/the_nether"><a href="vanilla/data/minecraft/dimension_type/the_nether.json">minecraft:the_nether</a></pre>
<pre>
{
  "logical_height": 128,
  "infiniburn": "minecraft:infiniburn_nether",
  "effects": "minecraft:the_nether",
  "ambient_light": 0.1,
  "respawn_anchor_works": true,
  "has_raids": false,
  "min_y": 0,
  "height": 256,
  "natural": false,
  "coordinate_scale": 8.0,
  "piglin_safe": true,
  "bed_works": false,
  "fixed_time": 18000,
  "has_skylight": false,
  "has_ceiling": true,
  "ultrawarm": true
}
</pre>

<pre class="file" id="minecraft/dimension_type/the_end"><a href="vanilla/data/minecraft/dimension_type/the_end.json">minecraft:the_end</a></pre>
<pre>
{
  "logical_height": 256,
  "infiniburn": "minecraft:infiniburn_end",
  "effects": "minecraft:the_end",
  "ambient_light": 0.0,
  "respawn_anchor_works": false,
  "has_raids": true,
  "min_y": 0,
  "height": 256,
  "natural": false,
  "coordinate_scale": 1.0,
  "piglin_safe": false,
  "bed_works": false,
  "fixed_time": 6000,
  "has_skylight": false,
  "has_ceiling": false,
  "ultrawarm": false
}
</pre>


<h3 id="维度实例">§2.11.3 实例</h3>
<p>定义好新的维度之后，我们还需要为其设计传送方式。简单的可以使用物品触发，见<a href="#右键交互">右键交互</a>。更常见的则是使用多方块结构为传送检测方式。</p>
<p class="ex">定义一个新的维度，其中仅有繁花森林生物群系。使用高花摆放成八边形并在中间放置白色羊毛激活传送门。</p>
<pre class="file" id="cpp/dimension/flower">cpp/dimension/flower.json</pre>
<pre>
{
  "type": "cpp:flower",
  "generator": {
    "type": "minecraft:noise",
    "seed": 20200602,
    "settings": {
      "bedrock_roof_position":256,
      "bedrock_floor_position": 0,
      "sea_level": 63,
      "disable_mob_generation": true,
      "default_block": {
        "Name": "minecraft:dirt"
      },
      "default_fluid": {
        "Name": "minecraft:water",
        "Properties": {
          "level": "0"
        }
      },
      "noise": {
        "top_slide": {
          "target": 0,
          "size": 1,
          "offset": 1
        },
        "bottom_slide": {
          "target": 0,
          "size": 1,
          "offset": 1
        },
        "sampling": {
          "xz_scale": 0.01,
          "xz_factor": 1.0,
          "y_scale": 0.01,
          "y_factor": 1.0
        },
        "size_vertical": 1,
        "size_horizontal": 1,
        "min_y": 0,
        "height": 128,
        "density_factor": 1.0,
        "density_offset": 0.0,
        "simplex_surface_noise": false
      },
      "structures": {
        "structures": {
          "mineshaft": {
            "spacing": 2000,
            "separation": 1000,
            "salt": 20200602
          },
          "ruined_portal": {
            "spacing": 2000,
            "separation": 1000,
            "salt": 20200602
          }
        }
      }
    },
    "biome_source": {
      "biome": "minecraft:flower_forest",
      "type": "minecraft:fixed",
      "seed": 20200602
    }
  }
}
</pre>
<pre class="file" id="cpp/dimension_type/flower">cpp/dimension_type/flower.json</pre>
<pre>
{
  "ultrawarm": false,
  "natural": false,
  "coordinate_scale": 1.0,
  "has_skylight": true,
  "has_ceiling": false,
  "ambient_light": 1,
  "fixed_time": 6000,
  "piglin_safe": false,
  "bed_works": true,
  "respawn_anchor_works": true,
  "has_raids": false,
  "logical_height": 256,
  "infiniburn": "minecraft:infiniburn_overworld"
}
</pre>

<pre class="file" id="cpp/advancements/block/white_wool">cpp/advancements/block/white_wool.json</pre>
<pre>
{
  "criteria": {
    "white_wool": {
      "trigger": "minecraft:placed_block",
      "conditions": {
        "block": "minecraft:white_wool"
      }
    }
  },
  "rewards": {
    "function": "cpp:block/reset/white_wool"
  }
}
</pre>
<pre class="file" id="cpp/functions/block/reset/white_wool">cpp:block/reset/white_wool</pre>
<pre>
advancement revoke @s only cpp:block/white_wool
scoreboard players set #block_id cppValue 3
function <a href="#cpp/functions/misc/loc/pos">cpp:misc/loc/pos</a>
<span class="comment"># 旧版本中我们使用药水云作为标记实体</span>
execute as @e[type=marker,distance=..9,tag=cpp_loc_block_pos] at @s align xyz if predicate <a href="#cpp/predicates/flower_portal">cpp:flower_portal</a> run function <a href="#cpp/functions/block/put/white_wool">cpp:block/put/white_wool</a>
kill @e[type=marker,distance=..9,tag=cpp_loc_block_pos]
</pre>
<pre class="file" id="cpp/functions/block/put/white_wool">cpp:block/put/white_wool</pre>
<pre>
summon marker ~0.5 ~ ~0.5 {Tags:["cpp_aec_marker","cpp_flower_portal"]}
setblock ~ ~ ~ end_gateway
</pre>
<pre class="file" id="cpp/predicates/flower_portal">cpp/predicates/flower_portal.json</pre>
<pre>
[
  {
    "condition": "minecraft:location_check",
    "offsetX": 2,
    "offsetZ": 2,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  },
  {
    "condition": "minecraft:location_check",
    "offsetX": 2,
    "offsetZ": -2,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  },
  {
    "condition": "minecraft:location_check",
    "offsetX": -2,
    "offsetZ": 2,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  },
  {
    "condition": "minecraft:location_check",
    "offsetX": -2,
    "offsetZ": -2,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  },
  {
    "condition": "minecraft:location_check",
    "offsetX": 3,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  },
  {
    "condition": "minecraft:location_check",
    "offsetX": -3,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  },
  {
    "condition": "minecraft:location_check",
    "offsetZ": 3,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  },
  {
    "condition": "minecraft:location_check",
    "offsetZ": -3,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  }
]
</pre>
<pre class="file" id="cpp/predicates/flower_portal_done">cpp/predicates/flower_portal_done.json</pre>
<pre>
[
  {
    "condition": "minecraft:location_check",
    "predicate": {
      "block": {
        "blocks": ["minecraft:end_gateway"]
      }
    }
  },
  {
    "condition": "minecraft:location_check",
    "offsetX": 2,
    "offsetZ": 2,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  },
  {
    "condition": "minecraft:location_check",
    "offsetX": 2,
    "offsetZ": -2,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  },
  {
    "condition": "minecraft:location_check",
    "offsetX": -2,
    "offsetZ": 2,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  },
  {
    "condition": "minecraft:location_check",
    "offsetX": -2,
    "offsetZ": -2,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  },
  {
    "condition": "minecraft:location_check",
    "offsetX": 3,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  },
  {
    "condition": "minecraft:location_check",
    "offsetX": -3,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  },
  {
    "condition": "minecraft:location_check",
    "offsetZ": 3,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  },
  {
    "condition": "minecraft:location_check",
    "offsetZ": -3,
    "predicate": {
      "block": {
        "tag": "minecraft:tall_flowers",
        "state": {
          "half": "lower"
        }
      }
    }
  }
]
</pre>

<p>检测传送门是否完整。检测玩家位置来传送。</p>
<pre class="file">cpp:tick</pre>
<pre>
execute as @e[type=marker,tag=cpp_flower_portal] at @s unless predicate <a href="#cpp/predicates/flower_portal_done">cpp:flower_portal_done</a> run function <a href="#cpp/functions/misc/flower_portal">cpp:misc/flower_portal</a>
execute as @a at @s[predicate=<a href="#cpp/predicates/in_overworld">cpp:in_overworld</a>,predicate=<a href="#cpp/predicates/flower_portal_done">cpp:flower_portal_done</a>] run function <a href="#cpp/functions/misc/to_flower">cpp:misc/to_flower</a>
execute as @a at @s[predicate=<a href="#cpp/predicates/in_flower">cpp:in_flower</a>,predicate=<a href="#cpp/predicates/flower_portal_done">cpp:flower_portal_done</a>] run function <a href="#cpp/functions/misc/to_overworld">cpp:misc/to_overworld</a>
</pre>
<pre class="file" id="cpp/functions/misc/flower_portal">cpp:misc/flower_portal</pre>
<pre>
kill @s
setblock ~ ~ ~ white_wool
</pre>
<pre class="file" id="cpp/predicates/in_overworld">cpp/predicates/in_overworld.json</pre>
<pre>
{
  "condition": "minecraft:location_check",
  "predicate":{
    "dimension": "minecraft:overworld"
  }
}
</pre>
<pre class="file" id="cpp/predicates/in_flower">cpp/predicates/in_flower.json</pre>
<pre>
{
  "condition": "minecraft:location_check",
  "predicate":{
    "dimension": "cpp:flower"
  }
}
</pre>
<pre class="file" id="cpp/functions/misc/to_flower">cpp:misc/to_flower</pre>
<pre>
execute in cpp:flower run tp ~ ~ ~
execute at @s run spreadplayers ~ ~ 1 10 false @s
</pre>
<pre class="file" id="cpp/functions/misc/to_overworld">cpp:misc/to_overworld</pre>
<pre>
execute in overworld run tp ~ ~ ~
execute at @s run spreadplayers ~ ~ 1 10 false @s
</pre>

<h3 id="自定义世界">§2.11.4 自定义世界</h3>
<p>自定义世界是一种世界类型，它用自定的特性取代了世界的普通地形。创建世界时，点击<code>更多选项->导入世界->选择JSON文件</code>即可。这种方式还可以用来创建额外的维度而不借助于数据包，但是默认只能使用命令 <code>/execute in <i>维度名称</i></code> 进入额外的维度。</p>
<pre class="file" id="自定义世界/JSON格式">JSON格式</pre>
<pre>
{
  "bonus_chest": true 或 false, <span class="comment">是否会生成奖励箱</span>
  "generate_features": true 或 false, <span class="comment">是否生成建筑</span>
  "seed": 整数, <span class="comment">种子</span>
  "dimensions": [ <span class="comment">维度列表</span>
    "minecraft:overworld": <a href="#维度/JSON格式">维度JSON对象</a>, <span class="comment">主世界</span>
    "minecraft:the_nether": <a href="#维度/JSON格式">维度JSON对象</a>, <span class="comment">下界</span>
    "minecraft:the_end": <a href="#维度/JSON格式">维度JSON对象</a>, <span class="comment">末地</span>
    "<a href="#维度">维度</a>命名空间ID": <a href="#维度/JSON格式">维度JSON对象</a> <span class="comment">其它维度</span>
  ]
}
</pre>


<h2 id="自定义世界生成">§2.12 自定义世界生成</h2>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/自定义世界生成" class="wiki">自定义世界生成</a></li>
  <li><a href="https://minecraft.wiki/w/Custom_world_generation" class="wikien">Custom world generation</a></li>
</ul>

<p>自定义世界生成 (Custom world generation) 允许数据包改变世界的生成方式，这需要和<a href="#维度">维度</a>配合使用。本节中列出的很多JSON内容的作用仍然需要测试。<a href="https://gitee.com/zhangshenxing/VanillaModTutorial/raw/master/files/vanilla_worldgen.zip">点此可下载原版所有的 <code>worldgen</code> 内容</a> (<a href="https://github.com/slicedlime/">slicedlime</a> 提供)。注意原版的维度和维度类型并不保存在原版数据包中。</p>

<h3 id="噪声设置">§2.12.1 噪声设置</h3>
<table><tbody>
<tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
<tr><th>文件路径</th><td><code><i>命名空间</i>/worldgen‌/noise_settings/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
<li><a href="https://zh.minecraft.wiki/w/自定义世界生成#噪声设置" class="wiki">噪声设置</a></li>
<li><a href="https://minecraft.wiki/w/Custom_world_generation#Noise_settings" class="wikien">Noise settings</a></li>
</ul>

<p>噪声设置 (noise_settings) 用于设置<a href="#维度">维度</a>生成的噪声。噪声设置文件为JSON文件，格式可参考<a href="https://minecraft.wiki/w/Biome/Custom_world_generation#Noise_settings">Noise Settings – Official Minecraft Wiki</a>。噪声设置的命名空间ID<code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code>对应的文件为 <code><i>命名空间</i>/worldgen‌/noise_settings/<i>路径</i>/<i>文件名</i>.json</code>。</p>
<p>当维度的高度或最低高度发生改变时，再次进入该维度会导致区块 (<code>regions</code> 文件夹下文件)重新生成，但实体 (<code>entities</code> 文件夹下文件)会保留。</p>

<pre class="file" id="噪声设置JSON格式">噪声设置JSON格式</pre>
<pre>
{ 
  "bedrock_roof_position": 整数, <span class="comment">世界顶部Y坐标-基岩天花板的Y坐标, 如果它不在 0~世界高度范围 范围内, 则无基岩天花板</span>
  "bedrock_floor_position": 整数, <span class="comment">基岩地板的Y坐标-世界底部Y坐标，如果它不在 0~世界高度范围 范围内, 则无基岩地板</span>
  "sea_level": 整数, <span class="comment">海平面高度</span>
  "disable_mob_generation"：true 或 false, <span class="comment">是否禁止生物生成</span>
  "noise_caves_enabled": true 或 false, <span class="comment">是否生成噪声洞穴</span>
  "aquifers_enabled": true 或 false, <span class="comment">是否生成蓄水层</span>
  "deepslate_enabled": true 或 false, <span class="comment">是否将世界底部石头替换为深板岩</span>
  "ore_veins_enabled": true 或 false, <span class="comment">是否生成矿脉</span>
  "min_surface_level": 整数, <span class="comment">TBD</span>
  "default_block": { <span class="comment">决定世界地形顶部下方生成的方块</span>
    "Name": "方块命名空间ID",
    "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
      "方块状态名": "方块状态值"
    }
  },
  "default_fluid": { <span class="comment">海洋与湖泊所使用的方块</span>
    "Name": "命名空间ID", <span class="comment">流体</span>
    "Properties": {
      "流体状态名": "流体状态值"
    }
  },
  "structures": { <span class="comment">结构设置，参考<a href="#超平坦型维度">超平坦型维度</a>JSON格式的结构设置</span>
    "stronghold": { <span class="comment">可选，要塞的生成设置</span>
      "count": 1~4095 之间的整数,
      "spread": 0~1023 之间的整数, <span class="comment">设置为0时会使世界中某些位置上反复生成多个要塞</span>
      "distance": 0~1023 之间的整数
    },
    "structures": [ <span class="comment">该维度中会生成的结构，如果需要生成要塞也需在此列出</span>
      "<a href="https://zh.minecraft.wiki/w/Java版数据值#结构">结构</a>命名空间ID": { <span class="comment">注意这不是<a href="#结构地物">结构地物</a>命名空间ID，自定义的结构地物生成几率设置随同其对应的原版结构</span>
        "spacing": 正整数, <span class="comment">两个该种类的结构之间的平均距离，以区块为单位</span>
        "separation": 1~(spacing-1) 之间的整数, <span class="comment">两个该种类的结构之间的最小距离，以区块为单位</span>
        "salt": 整数 <span class="comment">影响结构内部生成</span>
      }
    ]
  }
  "noise": { <span class="comment">世界生成参数</span>
    "top_slide": { <span class="comment">世界地形的顶部曲线的设置，影响区域以地形顶部为中心，影响的高度为 size × size_vertical×4</span>
      "size": 非负整数,
      "target": 整数, <span class="comment">负值会使山丘更加圆润，正值会使其更加平坦</span>
      "offset": 整数 <span class="comment">移动影响区域，正值向下移动，负值向上移动</span>
    },
    "bottom_slide": { <span class="comment">世界地形的底部曲线的设置, 影响区域以地形底部为中心, 影响的高度为 size × size_vertical × 4</span>
      "size": 非负整数,
      "target": 整数, <span class="comment">负值会使浮岛底部更加圆润，正值会生成一个基岩地板</span>
      "offset": 整数 <span class="comment">移动影响区域，正值向下移动，负值向上移动</span>
    },
    "sampling": {
      "xz_scale": 正数值, <span class="comment">伸缩X和Z轴的噪声，更大的值会造成更复杂的水平形状</span>
      "xz_factor": 正数值, <span class="comment">平滑水平方向上的噪声</span>
      "y_scale": 正数值, <span class="comment">伸缩Y轴的噪声，更大的值会造成更复杂的垂直形状</span>
      "y_factor": 正数值 <span class="comment">平滑垂直方向上的噪声</span>
    },
    "size_vertical": 正整数, <span class="comment">改变陆块在Y轴上的比例。1至15之间的值可以逐渐地增加山丘高度，大于20的值将会使得所有陆地高于通常的海平面63，比32更高的值会使得通常的陆地高度到达100+</span>
    "size_horizontal": 正整数, <span class="comment">改变陆块在X和Z轴上的比例，生物群系不会因此改变</span>
    "min_y": -2048~2031 之间的整数, <span class="comment">此噪声中可以存在方块的最低高度</span>
    "height": 16的正整数倍, <span class="comment">世界的总高度，min_y + height 不能超过 2032</span>
    "density_factor": 数值, <span class="comment">地形自下而上的梯度的放缩比例，值越大地形越陡峭，负值会使地形上下颠倒。</span>
    "density_offset": -1~1 之间的数值, <span class="comment">地形中心高度的偏移比例</span>
    "random_density_offset": true 或 false (默认值), <span class="comment">可选，地形中心高度是否有额外的随机偏移比例</span>
    "simplex_surface_noise": true 或 false, <span class="comment">是否使用单形噪声替代柏林噪声来生成地形</span>
    "island_noise_override": true 或 false (默认值), <span class="comment">可选，该世界是否像末地一样以小岛环绕着主岛的形式生成</span>
    "amplified": true 或 false (默认值) <span class="comment">可选，是否为放大化地形</span>
  },    
  "octaves": {
    "erosion": {
      "firstOctave": -9,
      "amplitudes": [
        1.0,
        1.0,
        0.0,
        1.0,
        1.0
      ]
    },
    "weirdness": {
      "firstOctave": -7,
      "amplitudes": [
        1.0,
        2.0,
        1.0,
        0.0,
        0.0,
        0.0
      ]
    },
    "shift": {
      "firstOctave": -3,
      "amplitudes": [
        1.0,
        1.0,
        1.0,
        0.0
      ]
    },
    "temperature": {
      "firstOctave": -9,
      "amplitudes": [
        1.5,
        0.0,
        1.0,
        0.0,
        0.0,
        0.0
      ]
    },
    "humidity": {
      "firstOctave": -7,
      "amplitudes": [
        1.0,
        1.0,
        0.0,
        0.0,
        0.0,
        0.0
      ]
    },
    "continentalness": {
      "firstOctave": -9,
      "amplitudes": [
        1.0,
        1.0,
        2.0,
        2.0,
        2.0,
        1.0,
        1.0,
        1.0,
        1.0
      ]
    }
  }
}</pre>

<h4 id="可用的噪声设置">可用的噪声设置</h4>
<p>这些是 Minecraft 内部已生成的噪声设置命名空间ID，可直接使用。</p>
<pre>
<a href="vanilla/data/minecraft/worldgen/noise_settings/overworld.json">minecraft:overworld</a> <span class="comment">通常的主世界</span>
<a href="vanilla/data/minecraft/worldgen/noise_settings/amplified.json">minecraft:amplified</a> <span class="comment">放大化的主世界</span>
<a href="vanilla/data/minecraft/worldgen/noise_settings/nether.json">minecraft:nether</a> <span class="comment">通常的下界</span>
<a href="vanilla/data/minecraft/worldgen/noise_settings/caves.json">minecraft:caves</a> <span class="comment">类似下界的洞穴却拥有主世界地形特征的世界</span>
<a href="vanilla/data/minecraft/worldgen/noise_settings/end.json">minecraft:end</a> <span class="comment">通常的末地</span>
<a href="vanilla/data/minecraft/worldgen/noise_settings/floating_islands.json">minecraft:floating_islands</a> <span class="comment">浮空岛屿</span>
</pre>

<h3 id="生物群系">§2.12.2 生物群系</h3>
<table><tbody>
<tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
<tr><th>文件路径</th><td><code><i>命名空间</i>/worldgen‌/biome/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
<li><a href="https://zh.minecraft.wiki/w/自定义世界生成#生物群系" class="wiki">生物群系</a></li>
<li><a href="https://minecraft.wiki/w/Biome/JSON_format" class="wikien">Biome/JSON format</a></li>
</ul>
<p>生物群系 (Biome) 规定了生物群系的特性，可用于<a href="#维度">维度</a>JSON文件的相应参数。</p>

<pre class="file" id="生物群系JSON格式">生物群系JSON格式</pre>
<pre>
{
  "depth": 数值, <span class="comment">深度，用于地形噪声生成，正值被认为是陆地，负值被认为是海洋</span>
  "scale": 数值, <span class="comment">比例，用于地形噪声生成，越大地形越陡峭</span>
  "precipitation": "none", "rain" 或 "snow", <span class="comment">降雨量，分别表示永不下雨、下雨和下雪。若为 snow 则自然生成的兔子为红眼白毛或黑白斑点</span>
  "category": "none", "taiga", "extreme_hills", "jungle", "mesa", "plains", "savanna", "icy", "the_end", "beach", "forest", "ocean", "desert", "river", "swamp", "mushroom" 或 "nether", <span class="comment">ocean 会采用海洋的温度体系；若玩家位于 ocean 和 river 水下会听到水下音乐而非一般的音乐；mushroom 不会生成僵尸围城和灾厄巡逻队；desert 且 precipitation 不为 snow 时生成的兔子为金黄色； water_ambient 类别的生物在 river 生成几率更低；海底神殿仅可能在 "ocean" 或 "river" 生成</span>
  "temperature": 数值, <span class="comment">温度, 控制草和树叶的颜色以及雪傀儡是否会受伤</span>
  "temperature_modifier": "none" (默认值) 或 "frozen", <span class="comment">可选，使用特殊的草温度选项</span>
  "downfall": 数值, <span class="comment">控制草和树叶的颜色, 超过 0.85 会使火焰蔓延更快</span>
  "player_spawn_friendly": true 或 false, <span class="comment">该生物群系是否对新玩家友好，世界重生点会被设置到定义为 true 的生物群系</span>
  "creature_spawn_probability": 0~1 之间的数值, <span class="comment">生物的基础生成成功率，值越低则该生物群系首次被加载时生成的生物越少</span>
  "effects": {
    "sky_color": RGB颜色的整数形式, <span class="comment">天空的颜色</span>
    "fog_color": RGB颜色的整数形式, <span class="comment">迷雾的颜色</span>
    "water_color": RGB颜色的整数形式, <span class="comment">水的颜色</span>
    "water_fog_color": RGB颜色的整数形式, <span class="comment">水下迷雾的颜色</span>
    "foliage_color": RGB颜色的整数形式, <span class="comment">可选，树叶的颜色，若无则根据该群系的 humidity 和 temperature 来设定</span>
    "grass_color": RGB颜色的整数形式, <span class="comment">可选，草的颜色，若无则根据该群系的 humidity 和 temperature 来设定</span>
    "grass_color_modifier": "none" (默认值), "dark_forest" 或 "swamp", <span class="comment">可选，使用特殊的草颜色</span>
    "particle": { <span class="comment">可选, 该生物群系的颗粒效果</span>
      "probability": 数值, <span class="comment">颗粒的生成几率</span>
      "options": {
        "type": "block" 或 "falling_dust", <span class="comment">摧毁方块的颗粒或浮起而未下落的方块颗粒</span>
        "Name": "方块命名空间ID",
        "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
          "方块状态名": "方块状态值"
        }
      或
        "type": "dust", <span class="comment">粉状颗粒</span>
        "r": 0~1 之间的数值, <span class="comment">红色分量</span>
        "g": 0~1 之间的数值, <span class="comment">绿色分量</span>
        "b": 0~1 之间的数值, <span class="comment">蓝色分量</span>
        "scale": 数值 <span class="comment">颗粒大小放缩</span>
      或
        "type": "item", <span class="comment">消耗物品的颗粒</span>
        "id": "物品命名空间ID"
        "Count": 整数, <span class="comment">物品数量</span>
        "tag": "字符串" <span class="comment">物品NBT</span>
      }
    },
    "ambient_sound": "<a href="#音效">音效</a>命名空间ID", <span class="comment">可选，环境音效</span>
    "mood_sound": { <span class="comment">可选，氛围音效</span>
      "sound": "<a href="#音效">音效</a>命名空间ID",
      "tick_delay": 整数, <span class="comment">TBD</span>
      "block_search_extent": 整数, <span class="comment">TBD</span>
      "offset": 数值 <span class="comment">TBD</span>
    },
    "additions_sound": { <span class="comment">可选，额外的音效</span>
      "sound": "<a href="#音效">音效</a>命名空间ID",
      "tick_chance": 数值 <span class="comment">TBD</span>
    },
    "music": { <span class="comment">可选，音乐</span>
      "sound": "<a href="#音效">音效</a>命名空间ID",
      "min_delay": 整数, <span class="comment">TBD</span>
      "max_delay": 整数, <span class="comment">TBD</span>
      "replace_current_music": true 或 false <span class="comment">是否替换已播放的音乐</span>
    }
  },
  "surface_builder": "<a href="#地表生成器">地表生成器</a>命名空间ID",
  "carvers": {<span class="comment">可选</span>
    "air": [ <span class="comment">可选，用于填充空气的地形雕刻器列表</span>
       "<a href="#地形雕刻器">地形雕刻器</a>命名空间ID"
    ],
    "liquid": [ <span class="comment">可选，用于填充液体的地形雕刻器列表</span>
      "<a href="#地形雕刻器">地形雕刻器</a>命名空间ID"
    ],
  },
  "features": [ <span class="comment">该列表共10项，生成时会根据它们生成地物的种子，然后按列表来依次生成每一项列表中的所有地物，可以为空列表。</span>
    [
      "<a href="#地物">地物</a>命名空间ID" <span class="comment">内部特征类型 RAW_GENERATION，原版未使用</span>
    ],
    [
      "<a href="#地物">地物</a>命名空间ID" <span class="comment">内部特征类型 LAKES，原版用于生成湖和熔岩湖</span>
    ],
    [
      "<a href="#地物">地物</a>命名空间ID" <span class="comment">内部特征类型 LOCAL_MODIFICATIONS，原版用于生成针叶林和冰刺之地的石头</span>
    ],
    [
      "<a href="#地物">地物</a>命名空间ID" <span class="comment">内部特征类型 UNDERGROUND_STRUCTURES，原版用于生成地牢和主世界化石</span>
    ],
    [
      "<a href="#地物">地物</a>命名空间ID" <span class="comment">内部特征类型 SURFACE_STRUCTURES，原版用于生成沙漠水井和蓝冰</span>
    ],
    [
      "<a href="#地物">地物</a>命名空间ID" <span class="comment">内部特征类型 STRONGHOLDS，原版未使用</span>
    ],
    [
      "<a href="#地物">地物</a>命名空间ID" <span class="comment">内部特征类型 UNDERGROUND_ORES，原版用于生成主世界石头中的矿脉、泥土砂砾石头变种和水下沙子砂砾粘土块堆</span>
    ],
    [
      "<a href="#地物">地物</a>命名空间ID" <span class="comment">内部特征类型 UNDERGROUND_DECORATION，原版用于生成主世界的被虫蛀的方块堆、下界砂砾和黑石堆、下界矿脉</span>
    ],
    [
      "<a href="#地物">地物</a>命名空间ID" <span class="comment">
        内部特征类型 VEGETAL_DECORATION，默认用于生成树、竹子、仙人掌、海带、其它地下和海底作物以及涌泉
        注意树的位置是固定的，也就是说如果该列表有多个 "type": "minecraft:tree" 的地物，则只有第一个会生效，之后的生成会被阻挡。想要各种地物都有几率生成，需要使用随机选择的地物(WIP)</span>
    ],
    [
      "<a href="#地物">地物</a>命名空间ID"
      <span class="comment">内部特征类型 TOP_LAYER_MODIFICATION，默认用于生成地表结冰</span>
    ]
  ],
  "starts": [ <span class="comment">该生物群系生成的结构地物列表</span>
    "<a href="#结构地物">结构地物</a>命名空间ID"
  ],
  "spawners": { <span class="comment">生物生成</span>
    "生物分类": [ <span class="comment">包括 monster, creature, ambient, water_creature, water_ambient, misc</span>
      {
        "type": "生物命名空间ID",
        "weight": 整数, <span class="comment">权重</span>
        "minCount": 整数, <span class="comment">最小数量</span>
        "maxCount": 整数 <span class="comment">最大数量</span>
      }
    ]
  },
  "spawn_costs": {<span class="comment">为特定实体设置生成几率</span>
    "生物命名空间ID": {<span class="comment">可选</span>
      "energy_budget": 数值, <span class="comment">该实体的生成预算，此值越大生成的越多</span>
      "charge": 数值 <span class="comment">该实体的生成代价，此值越大生成的越少</span>
    }
  }
}</pre>

<h4 id="可用的生物群系">可用的生物群系</h4>
<p>这些是 Minecraft 内部已生成的生物群系命名空间ID，可直接使用。</p>
<pre>
<a href="vanilla/data/minecraft/worldgen/biome/badlands.json">minecraft:badlands</a>
<a href="vanilla/data/minecraft/worldgen/biome/badlands_plateau.json">minecraft:badlands_plateau</a>
<a href="vanilla/data/minecraft/worldgen/biome/bamboo_jungle.json">minecraft:bamboo_jungle</a>
<a href="vanilla/data/minecraft/worldgen/biome/bamboo_jungle_hills.json">minecraft:bamboo_jungle_hills</a>
<a href="vanilla/data/minecraft/worldgen/biome/basalt_deltas.json">minecraft:basalt_deltas</a>
<a href="vanilla/data/minecraft/worldgen/biome/beach.json">minecraft:beach</a>
<a href="vanilla/data/minecraft/worldgen/biome/birch_forest.json">minecraft:birch_forest</a>
<a href="vanilla/data/minecraft/worldgen/biome/birch_forest_hills.json">minecraft:birch_forest_hills</a>
<a href="vanilla/data/minecraft/worldgen/biome/cold_ocean.json">minecraft:cold_ocean</a>
<a href="vanilla/data/minecraft/worldgen/biome/crimson_forest.json">minecraft:crimson_forest</a>
<a href="vanilla/data/minecraft/worldgen/biome/dark_forest.json">minecraft:dark_forest</a>
<a href="vanilla/data/minecraft/worldgen/biome/dark_forest_hills.json">minecraft:dark_forest_hills</a>
<a href="vanilla/data/minecraft/worldgen/biome/deep_cold_ocean.json">minecraft:deep_cold_ocean</a>
<a href="vanilla/data/minecraft/worldgen/biome/deep_frozen_ocean.json">minecraft:deep_frozen_ocean</a>
<a href="vanilla/data/minecraft/worldgen/biome/deep_lukewarm_ocean.json">minecraft:deep_lukewarm_ocean</a>
<a href="vanilla/data/minecraft/worldgen/biome/deep_ocean.json">minecraft:deep_ocean</a>
<a href="vanilla/data/minecraft/worldgen/biome/deep_warm_ocean.json">minecraft:deep_warm_ocean</a>
<a href="vanilla/data/minecraft/worldgen/biome/desert.json">minecraft:desert</a>
<a href="vanilla/data/minecraft/worldgen/biome/desert_hills.json">minecraft:desert_hills</a>
<a href="vanilla/data/minecraft/worldgen/biome/desert_lakes.json">minecraft:desert_lakes</a>
<a href="vanilla/data/minecraft/worldgen/biome/dripstone_caves.json">minecraft:dripstone_caves</a>
<a href="vanilla/data/minecraft/worldgen/biome/end_barrens.json">minecraft:end_barrens</a>
<a href="vanilla/data/minecraft/worldgen/biome/end_highlands.json">minecraft:end_highlands</a>
<a href="vanilla/data/minecraft/worldgen/biome/end_midlands.json">minecraft:end_midlands</a>
<a href="vanilla/data/minecraft/worldgen/biome/eroded_badlands.json">minecraft:eroded_badlands</a>
<a href="vanilla/data/minecraft/worldgen/biome/flower_forest.json">minecraft:flower_forest</a>
<a href="vanilla/data/minecraft/worldgen/biome/forest.json">minecraft:forest</a>
<a href="vanilla/data/minecraft/worldgen/biome/frozen_ocean.json">minecraft:frozen_ocean</a>
<a href="vanilla/data/minecraft/worldgen/biome/frozen_river.json">minecraft:frozen_river</a>
<a href="vanilla/data/minecraft/worldgen/biome/giant_spruce_taiga.json">minecraft:giant_spruce_taiga</a>
<a href="vanilla/data/minecraft/worldgen/biome/giant_spruce_taiga_hills.json">minecraft:giant_spruce_taiga_hills</a>
<a href="vanilla/data/minecraft/worldgen/biome/giant_tree_taiga.json">minecraft:giant_tree_taiga</a>
<a href="vanilla/data/minecraft/worldgen/biome/giant_tree_taiga_hills.json">minecraft:giant_tree_taiga_hills</a>
<a href="vanilla/data/minecraft/worldgen/biome/gravelly_mountains.json">minecraft:gravelly_mountains</a>
<a href="vanilla/data/minecraft/worldgen/biome/ice_spikes.json">minecraft:ice_spikes</a>
<a href="vanilla/data/minecraft/worldgen/biome/jungle.json">minecraft:jungle</a>
<a href="vanilla/data/minecraft/worldgen/biome/jungle_edge.json">minecraft:jungle_edge</a>
<a href="vanilla/data/minecraft/worldgen/biome/jungle_hills.json">minecraft:jungle_hills</a>
<a href="vanilla/data/minecraft/worldgen/biome/lukewarm_ocean.json">minecraft:lukewarm_ocean</a>
<a href="vanilla/data/minecraft/worldgen/biome/lush_caves.json">minecraft:lush_caves</a>
<a href="vanilla/data/minecraft/worldgen/biome/modified_badlands_plateau.json">minecraft:modified_badlands_plateau</a>
<a href="vanilla/data/minecraft/worldgen/biome/modified_gravelly_mountains.json">minecraft:modified_gravelly_mountains</a>
<a href="vanilla/data/minecraft/worldgen/biome/modified_jungle.json">minecraft:modified_jungle</a>
<a href="vanilla/data/minecraft/worldgen/biome/modified_jungle_edge.json">minecraft:modified_jungle_edge</a>
<a href="vanilla/data/minecraft/worldgen/biome/modified_wooded_badlands_plateau.json">minecraft:modified_wooded_badlands_plateau</a>
<a href="vanilla/data/minecraft/worldgen/biome/mountains.json">minecraft:mountains</a>
<a href="vanilla/data/minecraft/worldgen/biome/mountain_edge.json">minecraft:mountain_edge</a>
<a href="vanilla/data/minecraft/worldgen/biome/mushroom_fields.json">minecraft:mushroom_fields</a>
<a href="vanilla/data/minecraft/worldgen/biome/mushroom_field_shore.json">minecraft:mushroom_field_shore</a>
<a href="vanilla/data/minecraft/worldgen/biome/nether_wastes.json">minecraft:nether_wastes</a>
<a href="vanilla/data/minecraft/worldgen/biome/ocean.json">minecraft:ocean</a>
<a href="vanilla/data/minecraft/worldgen/biome/plains.json">minecraft:plains</a>
<a href="vanilla/data/minecraft/worldgen/biome/river.json">minecraft:river</a>
<a href="vanilla/data/minecraft/worldgen/biome/savanna.json">minecraft:savanna</a>
<a href="vanilla/data/minecraft/worldgen/biome/savanna_plateau.json">minecraft:savanna_plateau</a>
<a href="vanilla/data/minecraft/worldgen/biome/shattered_savanna.json">minecraft:shattered_savanna</a>
<a href="vanilla/data/minecraft/worldgen/biome/shattered_savanna_plateau.json">minecraft:shattered_savanna_plateau</a>
<a href="vanilla/data/minecraft/worldgen/biome/small_end_islands.json">minecraft:small_end_islands</a>
<a href="vanilla/data/minecraft/worldgen/biome/snowy_beach.json">minecraft:snowy_beach</a>
<a href="vanilla/data/minecraft/worldgen/biome/snowy_mountains.json">minecraft:snowy_mountains</a>
<a href="vanilla/data/minecraft/worldgen/biome/snowy_taiga.json">minecraft:snowy_taiga</a>
<a href="vanilla/data/minecraft/worldgen/biome/snowy_taiga_hills.json">minecraft:snowy_taiga_hills</a>
<a href="vanilla/data/minecraft/worldgen/biome/snowy_taiga_mountains.json">minecraft:snowy_taiga_mountains</a>
<a href="vanilla/data/minecraft/worldgen/biome/snowy_tundra.json">minecraft:snowy_tundra</a>
<a href="vanilla/data/minecraft/worldgen/biome/soul_sand_valley.json">minecraft:soul_sand_valley</a>
<a href="vanilla/data/minecraft/worldgen/biome/stone_shore.json">minecraft:stone_shore</a>
<a href="vanilla/data/minecraft/worldgen/biome/sunflower_plains.json">minecraft:sunflower_plains</a>
<a href="vanilla/data/minecraft/worldgen/biome/swamp.json">minecraft:swamp</a>
<a href="vanilla/data/minecraft/worldgen/biome/swamp_hills.json">minecraft:swamp_hills</a>
<a href="vanilla/data/minecraft/worldgen/biome/taiga.json">minecraft:taiga</a>
<a href="vanilla/data/minecraft/worldgen/biome/taiga_hills.json">minecraft:taiga_hills</a>
<a href="vanilla/data/minecraft/worldgen/biome/taiga_mountains.json">minecraft:taiga_mountains</a>
<a href="vanilla/data/minecraft/worldgen/biome/tall_birch_forest.json">minecraft:tall_birch_forest</a>
<a href="vanilla/data/minecraft/worldgen/biome/tall_birch_hills.json">minecraft:tall_birch_hills</a>
<a href="vanilla/data/minecraft/worldgen/biome/the_end.json">minecraft:the_end</a>
<a href="vanilla/data/minecraft/worldgen/biome/the_void.json">minecraft:the_void</a>
<a href="vanilla/data/minecraft/worldgen/biome/warm_ocean.json">minecraft:warm_ocean</a>
<a href="vanilla/data/minecraft/worldgen/biome/warped_forest.json">minecraft:warped_forest</a>
<a href="vanilla/data/minecraft/worldgen/biome/wooded_badlands_plateau.json">minecraft:wooded_badlands_plateau</a>
<a href="vanilla/data/minecraft/worldgen/biome/wooded_hills.json">minecraft:wooded_hills</a>
<a href="vanilla/data/minecraft/worldgen/biome/wooded_mountains.json">minecraft:wooded_mountains</a>
</pre>

<h3 id="地形雕刻器">§2.12.3 地形雕刻器</h3>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/worldgen‌/configured_carver/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/自定义世界生成#地形雕刻器" class="wiki">地形雕刻器</a></li>
  <li><a href="https://minecraft.wiki/w/Custom_world_generation#Carvers" class="wikien">Carvers</a></li>
</ul>

<p>地形雕刻器 (Carver) 用来在地形中雕刻出空气或液体的区域，被调用于<a href="#生物群系">生物群系</a>JSON文件的 <code>carvers</code>。</p>

<pre class="file" id="地形雕刻器JSON格式">地形雕刻器JSON格式</pre>
<pre>
{
  "type": "cave", "nether_cave", "canyon", "underwater_canyon" 或 "underwater_cave", <span class="comment">雕刻类型</span>
  "config": {
    "lava_level": {
      "above_bottom": 整数 <span class="comment">熔岩层与世界最底部高度差</span>
    },
    "aquifers_enabled": true 或 false, <span class="comment">是否使用蓄水层</span>
    "debug_settings": { <span class="comment">TBD，调试设置</span>
      "water_state": {
        "Name": "方块命名空间ID",
        "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
          "方块状态名": "方块状态值"
        }
      },
      "lava_state": {
        "Name": "方块命名空间ID",
        "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
          "方块状态名": "方块状态值"
        }
      },
      "barrier_state": {
        "Name": "方块命名空间ID",
        "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
          "方块状态名": "方块状态值"
        }
      },
      "air_state": {
        "Name": "方块命名空间ID",
        "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
          "方块状态名": "方块状态值"
        }
      }
    },
    "probability": 0~1 之间的数值, <span class="comment">雕刻几率</span>
    "y": { <span class="comment">TBD，雕刻的高度范围</span>
      "type": "minecraft:uniform" 或 "minecraft:biased_to_bottom",
      "min_inclusive": {
        "absolute": 正整数
      或
        "above_bottom": 正整数
      },
      "max_inclusive": {
        "absolute": 正整数
      或
        "below_top": 正整数
      },
      "inner": 正整数 <span class="comment">仅 biased_to_bottom 类型适用</span>
    },
    "yScale": <a href="#地形雕刻器数值">地形雕刻器数值</a>,
    "horizontal_radius_multiplier": <a href="#地形雕刻器数值">地形雕刻器数值</a>,
    "vertical_radius_multiplier": <a href="#地形雕刻器数值">地形雕刻器数值</a>,
    "floor_level": <a href="#地形雕刻器数值">地形雕刻器数值</a>, <span class="comment">仅 cave, nether_cave, underwater_cave 类型适用</span>
    "vertical_rotation": <a href="#地形雕刻器数值">地形雕刻器数值</a>, <span class="comment">仅 canyon, underwater_canyon 类型适用</span>
    "shape": { <span class="comment">仅 canyon, underwater_canyon 类型适用</span>
      "horizontal_radius_factor": <a href="#地形雕刻器数值">地形雕刻器数值</a>,
      "vertical_radius_default_factor": <a href="#地形雕刻器数值">地形雕刻器数值</a>,
      "vertical_radius_center_factor": <a href="#地形雕刻器数值">地形雕刻器数值</a>,
      "distance_factor": <a href="#地形雕刻器数值">地形雕刻器数值</a>,
      "thickness": <a href="#地形雕刻器数值">地形雕刻器数值</a>,
      "width_smoothness": 正整数
    }
  }
}</pre>

<pre class="file" id="地形雕刻器数值">地形雕刻器数值</pre>
<pre>
  数值
或
  {
    "type": "minecraft:uniform", <span class="comment">均匀分布</span>
    "value": {
      "min_inclusive": 数值,
      "max_exclusive": 数值
    }
  }
或
  {
    "type": "minecraft:trapezoid", <span class="comment">梯形分布</span>
    "value": {
      "min": 数值,
      "max": 数值,
      "plateau": 数值
    }
  }
</pre>

<h4 id="可用的地形雕刻器">可用的地形雕刻器</h4>
<p>这些是 Minecraft 内部已生成的地形雕刻器命名空间ID，可直接使用。</p>
<pre>
<a href="vanilla/data/minecraft/worldgen/configured_carver/canyon.json">minecraft:canyon</a> <span class="comment">峡谷</span>
<a href="vanilla/data/minecraft/worldgen/configured_carver/underwater_canyon.json">minecraft:underwater_canyon</a> <span class="comment">水下峡谷</span>
<a href="vanilla/data/minecraft/worldgen/configured_carver/canyon.json">minecraft:cave</a> <span class="comment">洞穴</span>
<a href="vanilla/data/minecraft/worldgen/configured_carver/underwater_cave.json">minecraft:underwater_cave</a> <span class="comment">水下洞穴</span>
<a href="vanilla/data/minecraft/worldgen/configured_carver/nether_cave.json">minecraft:nether_cave</a> <span class="comment">下界洞穴</span>
<a href="vanilla/data/minecraft/worldgen/configured_carver/ocean_cave.json">minecraft:ocean_cave</a> <span class="comment">海洋洞穴</span>
<a href="vanilla/data/minecraft/worldgen/configured_carver/prototype_canyon.json">minecraft:prototype_canyon</a> <span class="comment">预设峡谷</span>
<a href="vanilla/data/minecraft/worldgen/configured_carver/prototype_cave.json">minecraft:prototype_cave</a> <span class="comment">预设洞穴</span>
<a href="vanilla/data/minecraft/worldgen/configured_carver/prototype_crevice.json">minecraft:prototype_crevice</a> <span class="comment">预设裂缝</span>
<a href="vanilla/data/minecraft/worldgen/configured_carver/prototype_ocean_cave.json">minecraft:prototype_ocean_cave</a> <span class="comment">预设海洋洞穴</span>
</pre>


<h3 id="地表生成器">§2.12.4 地表生成器</h3>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/worldgen‌/configured_surface_builder/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/自定义世界生成#地表生成器" class="wiki">地表生成器</a></li>
  <li><a href="https://minecraft.wiki/w/Configured_surface_builder" class="wikien">Configured surface builder</a></li>
</ul>
<p>地表生成器 (Surface builder) 用来刻画地面的起伏和构成地形的默认方块，被调用于<a href="#生物群系">生物群系</a>JSON文件中的 <code>surface_builder</code>。</p>

<pre class="file" id="地表生成器JSON格式">地表生成器JSON格式</pre>
<pre>
{
  "type": "default"<span class="comment">默认</span>, "mountain"<span class="comment">山地</span>, "shattered_savanna"<span class="comment">破碎的热带草原</span>, "gravelly_mountain"<span class="comment">砂砾山地</span>, "giant_tree_taiga"<span class="comment">巨型针叶林</span>, "swamp"<span class="comment">沼泽</span>, "badlands"<span class="comment">恶地</span>, "wooded_badlands"<span class="comment">繁茂的恶地</span>, "eroded_badlands"<span class="comment">被风蚀的恶地</span>, "frozen_ocean"<span class="comment">冻洋</span>, "nether"<span class="comment">下界</span>, "nether_forest"<span class="comment">下界森林</span>, "soul_sand_valley"<span class="comment">灵魂沙峡谷</span>, "basalt_deltas"<span class="comment">玄武岩三角洲</span> 或 "nope"<span class="comment">无</span>,
  "config": {
    "top_material": { <span class="comment">顶层方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    },
    "under_material": { <span class="comment">顶层以下的方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    },
    "underwater_material": { <span class="comment">水下方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    }
  }
}</pre>

<h4 id="可用的地表生成器">可用的地表生成器</h4>
<p>这些是 Minecraft 内部已生成的地表生成器命名空间ID，可直接使用。</p>
<pre>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/badlands.json">minecraft:badlands</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/basalt_deltas.json">minecraft:basalt_deltas</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/crimson_forest.json">minecraft:crimson_forest</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/desert.json">minecraft:desert</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/end.json">minecraft:end</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/eroded_badlands.json">minecraft:eroded_badlands</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/frozen_ocean.json">minecraft:frozen_ocean</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/full_sand.json">minecraft:full_sand</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/giant_tree_taiga.json">minecraft:giant_tree_taiga</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/grass.json">minecraft:grass</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/gravelly_mountain.json">minecraft:gravelly_mountain</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/ice_spikes.json">minecraft:ice_spikes</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/mountain.json">minecraft:mountain</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/mycelium.json">minecraft:mycelium</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/nether.json">minecraft:nether</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/nope.json">minecraft:nope</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/ocean_sand.json">minecraft:ocean_sand</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/shattered_savanna.json">minecraft:shattered_savanna</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/soul_sand_valley.json">minecraft:soul_sand_valley</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/stone.json">minecraft:stone</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/swamp.json">minecraft:swamp</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/warped_forest.json">minecraft:warped_forest</a>
<a href="vanilla/data/minecraft/worldgen/configured_surface_builder/wooded_badlands.json">minecraft:wooded_badlands</a>
</pre>


<h3 id="地物">§2.12.5 地物</h3>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/worldgen‌/configured_feature/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/自定义世界生成#地物" class="wiki">地物</a></li>
  <li><a href="https://minecraft.wiki/w/Configured_feature" class="wikien">Configured feature</a></li>
</ul>

<p>地物 (Feature) 是指树、花、矿石等，被调用于<a href="#生物群系">生物群系</a>JSON文件的 <code>features</code> 中。</p>

<pre class="file" id="地物JSON格式">地物JSON格式</pre>
<pre>
{
  "type": "minecraft:tree",
  "config": {
    "trunk_provider": <a href="#方块状态类型">方块状态类型</a>JSON对象, <span class="comment">树干
      "trunk_placer": "fancy_trunk_placer" 时树干方块必须类似原木有方块状态 axis=x|y|z </span>
    "leaves_provider": <a href="#方块状态类型">方块状态类型</a>JSON对象, <span class="comment">树叶</span>
    "foliage_placer": { <span class="comment">树叶样式</span>
      "radius": <a href="#均匀分布的整数">均匀分布的整数</a> (minBase=0, maxBase=8, maxSpread=8), <span class="comment">半径</span>
      "offset": <a href="#均匀分布的整数">均匀分布的整数</a> (minBase=0, maxBase=8, maxSpread=8), <span class="comment">位移</span>

      "type": "minecraft:acacia_foliage_placer"<span class="comment">金合欢树叶型</span>
    或
      "type": "minecraft:dark_oak_foliage_placer"<span class="comment">深色橡树树叶型</span>
    或
      "type": "minecraft:blob_foliage_placer"<span class="comment">通常的橡树树叶和白桦树叶型</span>, "minecraft:bush_foliage_placer"<span class="comment">金字塔型</span>, "minecraft:fancy_foliage_placer"<span class="comment">球形树叶</span>或 "minecraft:jungle_foliage_placer"<span class="comment">丛林树型</span>,
      "height": 0~16 之间的整数, <span class="comment">树叶高度和尺寸</span>
    或
      "type": "minecraft:spruce_foliage_placer"<span class="comment">云杉树叶型</span>,
      "trunk_height": <a href="#均匀分布的整数">均匀分布的整数</a> (minBase=0, maxBase=16, maxSpread=8) <span class="comment">树干高度</span>
    或
      "type": "minecraft:pine_foliage_placer"<span class="comment">稀疏云杉树叶型</span>,
      "height": <a href="#均匀分布的整数">均匀分布的整数</a> (minBase=0, maxBase=16, maxSpread=8) <span class="comment">树叶高度</span>
    或
      "type": "minecraft:mega_pine_foliage_placer"<span class="comment">双层稀疏云杉树叶型</span>,
      "crown_height": <a href="#均匀分布的整数">均匀分布的整数</a> (minBase=0, maxBase=16, maxSpread=8) <span class="comment">第二层树叶高度</span>
    },
    "trunk_placer": { <span class="comment">树干样式</span>
      "type": "minecraft:straight_trunk_placer"<span class="comment">竖直型，类似桦树</span>, "minecraft:forking_trunk_placer"<span class="comment">单分叉型，类似金合欢</span>, "minecraft:giant_trunk_placer"<span class="comment">2×2竖直型，类似大云杉</span>, "minecraft:mega_jungle_trunk_placer"<span class="comment">大丛林木型</span>, "minecraft:dark_oak_trunk_placer"<span class="comment">深色橡木型</span> 或 "minecraft:fancy_trunk_placer"<span class="comment">多分叉型，类似大橡树</span>,
      "base_height": 0-32 之间的整数, <span class="comment">基础高度</span>
      "height_rand_a": 0-24 之间的整数, <span class="comment">与水平分叉有关的随机高度</span>
      "height_rand_b": 0-24 之间的整数 <span class="comment">与竖直分叉有关的随机高度</span>
    },
    "minimum_size": { <span class="comment">最小尺寸</span>
      "min_clipped_height": 0-80 之间的整数, <span class="comment">可选，最小剪切高度</span>

      "type": "minecraft:two_layers_feature_size", <span class="comment">两层</span>
      "limit": 0-81 之间的整数, 默认为 1, <span class="comment">可选，极限尺寸</span>
      "lower_size": 0-16 之间的整数, 默认为 0, <span class="comment">可选，最小尺寸</span>
      "upper_size": 0-16 之间的整数, 默认为 1 <span class="comment">可选，最大尺寸</span>
    或
      "type": "minecraft:three_layers_feature_size", <span class="comment">三层</span>
      "limit": 0-80 之间的整数, 默认为 1, <span class="comment">可选，极限尺寸</span>
      "upper_limit": 0-80 之间的整数, 默认为 1, <span class="comment">可选，最小尺寸</span>
      "lower_size": 0-16 之间的整数, 默认为 0, <span class="comment">可选，最小尺寸</span>
      "middle_size": 0-16 之间的整数, 默认为 1, <span class="comment">可选，最小尺寸</span>
      "upper_size": 0-16 之间的整数, 默认为 1 <span class="comment">可选，最大尺寸</span>
    },
    "decorators": [ <span class="comment">树干树叶上的装饰列表</span>
      {
        "type": "minecraft:trunk_vine"<span class="comment">树干藤蔓</span> 或 "minecraft:leave_vine"<span class="comment">树叶藤蔓</span>
      或
        "type": "minecraft:cocoa"<span class="comment">可可豆</span> 或 "minecraft:beehive"<span class="comment">蜂巢</span>,
        "probability": 0~1 之间的数值 <span class="comment">几率</span>
      或
        "type": "minecraft:alter_ground"<span class="comment">地面方块替换</span>,
        "provider": <a href="#方块状态类型">方块状态类型</a>JSON对象
      }
    ],
    "max_water_depth": 整数, 默认为 0, <span class="comment">可选，树在水下最大可生成深度</span>
    "ignore_vines": true 或 false (默认值), <span class="comment">可选，是否忽略藤蔓</span>
    "heightmap": "WORLD_SURFACE_WG", "WORLD_SURFACE", "OCEAN_FLOOR_WG", "OCEAN_FLOOR", "MOTION_BLOCKING" 或 "MOTION_BLOCKING_NO_LEAVES" <span class="comment">高度地图，用于随机</span>
  }
}

{
  "type": "minecraft:flower"<span class="comment">花</span> 或 "minecraft:random_patch", <span class="comment">随机堆</span>
  "config": {
    "state_provider": <a href="#方块状态类型">方块状态类型</a>JSON对象, <span class="comment">所使用的方块</span>
    "block_placer": {
      "type": "minecraft:simple_block_placer" <span class="comment">单个</span>
    或
      "type": "minecraft:double_plant_placer" <span class="comment">大型花</span>
    或
      "type": "minecraft:column_placer", <span class="comment">柱子</span>
      "min_size": 数值, <span class="comment">最小尺寸</span>
      "extra_size": 数值 <span class="comment">额外尺寸</span>
    },
    "whitelist": [ <span class="comment">TBD，白名单列表</span>
      {
        "Name": "方块命名空间ID",
        "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
          "方块状态名": "方块状态值"
        }
      }
    ],
    "blacklist": [ <span class="comment">TBD，黑名单列表</span>
      {
        "Name": "方块命名空间ID",
        "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
          "方块状态名": "方块状态值"
        }
      }
    ]
    "tries": 数值, 默认为 128, <span class="comment">可选，尝试次数</span>
    "xspread": 数值, 默认为 7, <span class="comment">可选，x轴扩散范围</span>
    "yspread": 数值, 默认为 3, <span class="comment">可选，y轴扩散范围</span>
    "zspread": 数值, 默认为 7, <span class="comment">可选，z轴扩散范围</span>
    "xspread": 数值, 默认为 7, <span class="comment">可选，x轴扩散范围</span>
    "can_replace", : true 或 false (默认值), <span class="comment">可选，是否替换原方块</span>
    "project": true (默认值) 或 false, <span class="comment">可选，TBD</span>
    "need_water": true 或 false (默认值) <span class="comment">可选，是否需要水</span>
  }
}

{
  "type": "minecraft:block_pile"<span class="comment">方块堆</span> 或 "minecraft:nether_forest_vegetation"<span class="comment">下界森林草</span>
  "config": {
    "state_provider": <a href="#方块状态类型">方块状态类型</a>JSON对象, <span class="comment">所使用的方块</span>
  }
}

{
  "type": "minecraft:spring_feature"<span class="comment">涌泉</span>,
  "config": {
    "state": { <span class="comment">所使用的流体</span>
      "Name": "命名空间ID", <span class="comment">流体</span>
      "Properties": {
        "流体状态名": "流体状态值"
      }
    },
    "requires_block_below": true (默认值) 或 false, <span class="comment">可选，下方是否需要方块</span>
    "rock_count": 数值, 默认为 4, <span class="comment">可选，TBD，岩石数量</span>
    "hole_count": 数值, 默认为 1, <span class="comment">可选，TBD，坑洞数量</span>
    "valid_blocks": [ <span class="comment">TBD，有效的方块列表</span>
      "Name": "方块命名空间ID"
    ]
  }
}

{
  "type": "minecraft:emerald_ore"<span class="comment">绿宝石矿</span>,
  "config": {
    "target": { <span class="comment">目标方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    },
    "state": { <span class="comment">自身方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    }
  }
}

{
  "type": "minecraft:huge_red_mushroom"<span class="comment">巨型红色蘑菇</span> 或 "minecraft:huge_brown_mushroom"<span class="comment">巨型棕色蘑菇</span>,
  "config": {
    "cap_provider": <a href="#方块状态类型">方块状态类型</a>JSON对象, <span class="comment">顶部方块</span>
    "stem_provider": <a href="#方块状态类型">方块状态类型</a>JSON对象, <span class="comment">柄部方块</span>
    "foliage_radius": 数值, 默认为 2 <span class="comment">可选，顶部大小</span>
  }
}

{
  "type": "minecraft:iceberg"<span class="comment">冰山</span>, "minecraft:forest_rock"<span class="comment">森林岩石</span> 或 "minecraft:lake"<span class="comment">湖</span>,
  "config": {
    "state": { <span class="comment">方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    }
  }
}

{
  "type": "minecraft:disk"<span class="comment">圆盘</span> 或 "minecraft:ice_patch"<span class="comment">冰堆</span>,
  "config": {
    "state": { <span class="comment">方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    },
    "radius": <a href="#均匀分布的整数">均匀分布的整数</a> (minBase=0, maxBase=4, maxSpread=4) <span class="comment">半径</span>
    "half_height": 0~4 之间的整数, <span class="comment">高度的一半</span>
    "targets": { <span class="comment">目标方块列表</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    }
  }
}

{
  "type": "minecraft:dripstone_cluster", <span class="comment">滴水石锥</span>
  "config": {
    "floor_to_ceiling_search_range": 1~512 之间的整数, <span class="comment">搜寻高度</span>
    "height": <a href="#均匀分布的整数">均匀分布的整数</a>, <span class="comment">(minBase=1, maxBase=64, maxSpread=64), 高度</span>
    "radius": <a href="#均匀分布的整数">均匀分布的整数</a>, <span class="comment">(minBase=1, maxBase=64, maxSpread=64), 半径</span>
    "max_stalagmite_stalactite_height_diff": 1~512 之间的整数, <span class="comment">石笋与钟乳石高度最大差</span>
    "height_deviation": 1~64 之间的整数, <span class="comment">高度偏差</span>
    "dripstone_block_layer_thickness": <a href="#均匀分布的整数">均匀分布的整数</a>, <span class="comment">(minBase=0, maxBase=64, maxSpread=64), 滴水石块层厚度</span>
    "density": 0~1 之间的<a href="#浮点数提供器">浮点数提供器</a>, <span class="comment">密度</span>
    "wetness": 0~1 之间的<a href="#浮点数提供器">浮点数提供器</a>, <span class="comment">湿度</span>
    "chance_of_dripstone_column_at_max_distance_from_center": 0~1 之间的浮点数, <span class="comment">距离中心点的最大距离几率</span>
    "max_distance_from_edge_affecting_chance_of_dripstone_column": 0~64 之间的整数, <span class="comment">边缘最大距离，影响滴水石柱几率</span>
    "max_distance_from_center_affecting_height_bias": 0~64 之间的整数 <span class="comment">中心最大距离，影响高度偏差</span>
  }
}

{
  "type": "minecraft:geode", <span class="comment">紫晶洞</span>
  "config": {
    "blocks": { <span class="comment">用来填充的方块</span>
      "filling_provider": <a href="#方块状态类型">方块状态类型</a>JSON对象, <span class="comment">内部填充方块</span>
      "inner_layer_provider": <a href="#方块状态类型">方块状态类型</a>JSON对象, <span class="comment">内层方块</span>
      "alternate_inner_layer_provider": <a href="#方块状态类型">方块状态类型</a>JSON对象, <span class="comment">镶嵌在内层的方块</span>
      "middle_layer_provider": <a href="#方块状态类型">方块状态类型</a>JSON对象, <span class="comment">中间层方块</span>
      "outer_layer_provider": <a href="#方块状态类型">方块状态类型</a>JSON对象, <span class="comment">外层方块</span>
      "inner_placements": [ <span class="comment">内层表面方块列表</span>
        {
          "Name": "方块命名空间ID",
          "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
            "方块状态名": "方块状态值"
          }
        }
      ]
    },
    "layers": {
      "filling": 0.01~50之间的数值, <span class="comment">可选，默认为 1.7</span>
      "inner_layer": 0.01~50之间的数值, <span class="comment">可选，默认为 2.2</span>
      "middle_layer": 0.01~50之间的数值, <span class="comment">可选，默认为 3.2</span>
      "outer_layer": 0.01~50之间的数值 <span class="comment">可选，默认为 4.2</span>
    },
    "crack": {
      "generate_crack_chance": 0~1之间的数值, <span class="comment">可选，默认为 1</span>
      "base_crack_size": 0~1之间的数值, <span class="comment">可选，默认为 2</span>
      "crack_point_offset": 0~1之间的数值, <span class="comment">可选，默认为 2</span>
    },
    "noise_multiplier": 0~1之间的数值, <span class="comment">可选，默认为 0.05</span>
    "use_potential_placements_chance": 0~1之间的数值, <span class="comment">可选，默认为 0.35</span>
    "use_alternate_layer0_chance": 0~1之间的数值, <span class="comment">可选，默认为 0.35</span>
    "placements_require_layer0_alternate": true(默认值) 或 false, <span class="comment">可选，默认为 0.05</span>
    "min_outer_wall_distance": 0~10之间的整数, <span class="comment">可选，默认为 4</span>
    "max_outer_wall_distance": 0~20之间的整数, <span class="comment">可选，默认为 6</span>
    "min_distribution_points": 0~10之间的整数, <span class="comment">可选，默认为 3</span>
    "max_distribution_points": 0~20之间的整数, <span class="comment">可选，默认为 5</span>
    "min_point_offset": 0~10之间的整数, <span class="comment">可选，默认为 1</span>
    "max_point_offset": 0~10之间的整数, <span class="comment">可选，默认为 3</span>
    "min_gen_offset": 整数, <span class="comment">可选，默认为 -16</span>
    "max_gen_offset": 整数 <span class="comment">可选，默认为 16</span>
  }
}

{
  "type": "minecraft:glow_lichen", <span class="comment">发光地衣</span>
  "config": {
    "search_range": 1~64 之间的整数, <span class="comment">可选，默认为10，搜寻范围</span>
    "chance_of_spreading": 0~1 之间的数值, <span class="comment">可选，默认为0.5，扩散几率</span>
    "can_place_on_floor": true 或 false(默认值), <span class="comment">可选，是否可放置在地板上</span>
    "can_place_on_ceiling": true 或 false(默认值), <span class="comment">可选，是否可放置在天花板上</span>
    "can_place_on_wall": true 或 false(默认值), <span class="comment">可选，是否可放置在方块侧面上</span>
    "can_be_placed_on": [ <span class="comment">可放置于之上的方块列表</span>
      {
        "Name": "方块命名空间ID",
        "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
          "方块状态名": "方块状态值"
        }
      }
    ]
  }
}

{
  "type": "minecraft:large_dripstone", <span class="comment">大型滴水石</span>
  "config": {
    "floor_to_ceiling_search_range": 1~512 之间的整数, <span class="comment">可选，默认为50，从底部向上的搜寻高度</span>
    "column_radius": <a href="#均匀分布的整数">均匀分布的整数</a>,
    "height_scale": 0~20 之间的<a href="#浮点数提供器">浮点数提供器</a>,
    "max_column_radius_to_cave_height_ratio": 0~1 之间的数值,
    "stalactite_bluntness": 0.1~10 之间的<a href="#浮点数提供器">浮点数提供器</a>,
    "stalagmite_bluntness": 0.1~10 之间的<a href="#浮点数提供器">浮点数提供器</a>,
    "wind_speed": 0~2 之间的<a href="#浮点数提供器">浮点数提供器</a>,
    "min_radius_for_wind": 0~100 之间的整数,
    "min_bluntness_for_wind": 0~5 之间的数值
  }
}

{
  "type": "minecraft:small_dripstone", <span class="comment">小型滴水石</span>
  "config": {
    "max_placements": 1~100 之间的整数,
    "empty_space_search_radius": 0~20 之间的整数,
    "max_offset_from_origin": 0~20 之间的整数,
    "chance_of_taller_dripstone": 0~1 之间的数值 <span class="comment">可选，默认为0.2</span>
  }
}

{
  "type": "minecraft:ore"<span class="comment">矿石</span> 或 "minecraft:scattered_ore", <span class="comment">散在矿石</span>
  "config": {
    "state": { <span class="comment">方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    },
    "size": 0~64 的整数, <span class="comment">矿脉大小</span>
    "discard_chance_on_air_exposure": 0~1 之间的数值, <span class="comment">暴露在空气中时的丢弃率</span>

    "target": { <span class="comment">目标方块要求</span>
      "predicate_type": "minecraft:always_true" <span class="comment">断言类型，总是成立</span>
    或
      "predicate_type": "minecraft:block_match" <span class="comment">断言类型，匹配方块</span>
      "block": "方块命名空间ID"
    或
      "predicate_type": "minecraft:blockstate_match", <span class="comment">断言类型，匹配方块状态</span>
      "block_state": {
        "Name": "方块命名空间ID",
        "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
          "方块状态名": "方块状态值"
        }
      }
    或
      "predicate_type": "minecraft:tag_match", <span class="comment">断言类型，匹配方块标签</span>
      "tag": "命名空间ID" <span class="comment">方块标签</span>
    或
      "predicate_type": "minecraft:random_block_match", <span class="comment">断言类型，随机匹配方块</span>
      "block": "方块命名空间ID",
      "probability": 0~1 之间的数值 <span class="comment">几率</span>
    或
      "predicate_type": "minecraft:random_blockstate_match", <span class="comment">断言类型，随机匹配方块状态</span>
      "block_state": {
        "Name": "方块命名空间ID",
        "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
          "方块状态名": "方块状态值"
        }
      },
      "probability": 0~1 之间的数值 <span class="comment">几率</span>
    }
  }
}

{
  "type": "minecraft:end_spike"<span class="comment">末地黑曜石柱</span>,
  "config": {
    "crystal_invulnerable": true 或 false (默认值), <span class="comment">可选，末影水晶是否无敌</span>
    "spikes": [ <span class="comment">柱子列表</span>
      {
        "centerX": 整数, 默认为 0, <span class="comment">可选，柱子中心的x坐标</span>
        "centerZ": 整数, 默认为 0, <span class="comment">可选，柱子中心的z坐标</span>
        "radius": 整数, 默认为 0, <span class="comment">可选，柱子半径</span>
        "height": 整数, 默认为 0, <span class="comment">可选，柱子高度</span>
        "guarded": true 或 false (默认值) <span class="comment">可选，末影水晶周围是否有铁栏杆笼子保护</span>
      }
    "crystal_beam_target": [ <span class="comment">可选，治愈激光定位到的位置</span>
      X坐标,
      Y坐标,
      Z坐标
    ]
  }
}

{
  "type": "minecraft:end_gateway"<span class="comment">末地折跃门</span>,
  "config": {
    "exit": [ <span class="comment">可选，当进入末地折跃门方块要把实体传送到的位置</span>
      目标位置的X坐标,
      目标位置的Y坐标,
      目标位置的Z坐标
    ],
    "exact": true 或 false <span class="comment">是否把实体准确传送到指定的坐标而不是传送到这个坐标附近的位置</span>
  }
}

{
  "type": "minecraft:seagrass"<span class="comment">海草</span> 或 "minecraft:bamboo"<span class="comment">竹子</span>,
  "config": {
    "probability": 0~1 之间的数值 <span class="comment">几率</span>
  }
}

{
  "type": "minecraft:sea_pickle"<span class="comment">海泡菜</span>,
  "config": {
    "count": <a href="#均匀分布的整数">均匀分布的整数</a> (minBase=-10, maxBase=128, maxSpread=128)
  }
}

{
  "type": "minecraft:simple_block"<span class="comment">单个方块</span>,
  "config": {
    "to_place": <a href="#方块状态类型">方块状态类型</a>, <span class="comment">将要放置的方块</span>
    "place_on": [ <span class="comment">将要放置的位置下方方块列表</span>
      {
        "Name": "方块命名空间ID",
        "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
          "方块状态名": "方块状态值"
        }
      }
    ],
    "place_in": [ <span class="comment">将要放置的位置的方块列表</span>
      {
        "Name": "方块命名空间ID",
        "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
          "方块状态名": "方块状态值"
        }
      }
    ],
    "place_under": [ <span class="comment">将要放置的位置上方方块列表</span>
      {
        "Name": "方块命名空间ID",
        "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
          "方块状态名": "方块状态值"
        }
      }
    ]
  }
}

{
  "type": "minecraft:huge_fungus"<span class="comment">巨型菌类</span>,
  "config": {
    "valid_base_block": { <span class="comment">底部基座方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    },
    "stem_state": { <span class="comment">菌柄方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    },
    "hat_state": { <span class="comment">顶部方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    },
    "decor_state": { <span class="comment">装饰方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    },
    "planted": true 或 false (默认值) <span class="comment">可选，TBD</span>
  }
}

{
  "type": "minecraft:basalt_columns"<span class="comment">玄武岩柱子</span>,
  "config": {
    "reach": <a href="#均匀分布的整数">均匀分布的整数</a> (minBase=0, maxBase=2, maxSpread=1), <span class="comment">TBD</span>
    "height": <a href="#均匀分布的整数">均匀分布的整数</a> (minBase=1, maxBase=5, maxSpread=5) <span class="comment">高度</span>
  }
}

{
  "type": "minecraft:delta_feature"<span class="comment">三角洲</span>,
  "config": {
    "contents": { <span class="comment">三角洲方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    },
    "rim": { <span class="comment">三角洲边缘方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    },
    "size": <a href="#均匀分布的整数">均匀分布的整数</a> (minBase=0, maxBase=8, maxSpread=8) <span class="comment">三角洲尺寸</span>
    "rim_size": <a href="#均匀分布的整数">均匀分布的整数</a> (minBase=0, maxBase=8, maxSpread=8) <span class="comment">三角洲边缘尺寸</span>
  }
}

{
  "type": "minecraft:netherrack_replace_blobs"<span class="comment">下界岩斑纹</span>,
  "config": {
    "target": { <span class="comment">替换的目标方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    },
    "state": { <span class="comment">方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    },
    "radius": <a href="#均匀分布的整数">均匀分布的整数</a> <span class="comment">半径</span>
  }
}

{
  "type": "minecraft:fill_layer", <span class="comment">填充层</span>
  "config": {
    "height": 整数, <span class="comment">高度</span>
    "state": { <span class="comment">方块</span>
      "Name": "方块命名空间ID",
      "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
        "方块状态名": "方块状态值"
      }
    }
  }
}

{
  "type": "minecraft:basalt_pillar"<span class="comment">玄武岩柱子</span>
}

{
  "type": "minecraft:blue_ice"<span class="comment">蓝冰</span>
}

{
  "type": "minecraft:bonus_chest"<span class="comment">出生奖励箱</span>
}

{
  "type": "minecraft:chorus_plant"<span class="comment">紫颂植物</span>
}

{
  "type": "minecraft:coral_claw"<span class="comment">珊瑚礁</span>
}

{
  "type": "minecraft:coral_mushroom"<span class="comment">珊瑚礁</span>
}

{
  "type": "minecraft:coral_tree"<span class="comment">珊瑚礁</span>
}

{
  "type": "minecraft:desert_well"<span class="comment">沙漠水井</span>
}

{
  "type": "minecraft:end_island"<span class="comment">末地岛</span>
}

{
  "type": "minecraft:fossil"<span class="comment">化石</span>
}

{
  "type": "minecraft:freeze_top_layer"<span class="comment">冰冻顶层</span>
}

{
  "type": "minecraft:glowstone_blob"<span class="comment">荧石堆</span>
}

{
  "type": "minecraft:ice_spike"<span class="comment">冰刺</span>
}

{
  "type": "minecraft:kelp"<span class="comment">海带</span>
}

{
  "type": "minecraft:monster_room"<span class="comment">地牢</span>
}

{
  "type": "minecraft:no_bonemeal_flower"<span class="comment">不可由骨粉催生的花</span>
}

{
  "type": "minecraft:no_op"<span class="comment">空白，用于替换已有地物</span>
}

{
  "type": "minecraft:freeze_top_layer"<span class="comment">冰冻顶层</span>
}

{
  "type": "minecraft:freeze_top_layer"<span class="comment">冰冻顶层</span>
}

<span class="comment">下面为地物修饰</span>
{
  "type": "minecraft:random_selector"<span class="comment">随机选择</span>,
  "config": {
    "features": [ <span class="comment">该列表中地物会被随机选中</span>
      {
        "feature": "命名空间ID" 或 <a href="#地物">地物</a>JSON对象, <span class="comment">地物</span>
        "chance": 0~1 之间的数值 <span class="comment">被选中的几率</span>
      }
    ],
    "default": "命名空间ID" 或 <a href="#地物">地物</a>JSON对象 <span class="comment">当上述均没有被选中时的地物</span>
  }
}
或
{
  "type": "minecraft:simple_random_selector"<span class="comment">简化的随机选择</span>,
  "config": {
    "features": [ <span class="comment">从该列表中等几率随机选择一个地物</span>
      {
        "feature": "命名空间ID" 或 <a href="#地物">地物</a>JSON对象 <span class="comment">地物</span>
      }
    ]
  }
}
或
{
  "type": "minecraft:random_boolean_selector"<span class="comment">随机二选一</span>,
  "config": {
    "feature_true": "命名空间ID" 或 <a href="#地物">地物</a>JSON对象, <span class="comment">地物</span>
    "feature_false": "命名空间ID" 或 <a href="#地物">地物</a>JSON对象 <span class="comment">地物</span>
  }
}

{
  "type": "minecraft:decorated"<span class="comment">带装饰的地物</span>,
  "config": {
    "feature": "命名空间ID" 或 <a href="#地物">地物</a>JSON对象, <span class="comment">地物</span>
    "decorator": "命名空间ID" 或 <a href="#装饰物">装饰物</a>JSON对象 <span class="comment">装饰物</span>
  }
}
</pre>

<p class="noindent">上述JSON格式中的</p>
<pre class="file" id="方块状态类型">方块状态类型</pre>
<pre>
{
  "type": "minecraft:plain_flower_provider"<span class="comment">通常的花</span> 或 "minecraft:forest_flower_provider"<span class="comment">繁花森林的花</span>
或
  "type": "minecraft:simple_state_provider"<span class="comment">简单情形</span> 或 "minecraft:rotated_block_provider"<span class="comment">可旋转</span>,
  "state": {
    "Name": "方块命名空间ID",
    "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
      "方块状态名": "方块状态值"
    }
  } 
或
  "type": "minecraft:weighted_state_provider", <span class="comment">带权重的方块状态类型</span>
  "entries": [ <span class="comment">允许的列表</span>
    {
      "weight": 0~1 之间的数值, <span class="comment">权重</span>
      "data": {
        "Name": "方块命名空间ID",
        "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
          "方块状态名": "方块状态值"
        }
      }
    }
  ]
}</pre>
<p>均匀分布的整数可以为一个JSON对象或一个非负整数。</p>
<pre class="file" id="均匀分布的整数">均匀分布的整数</pre>
<pre>
{<span class="comment">会从 <code>base</code> 至 <code>base+spread</code> 之间随机选取一个整数作为参数</span>
  "base": minBase~maxBase 之间的整数,
  "spread": 0~maxSpread 之间的整数, 如果无 maxSpread 限制, 则为任意非负整数
}
或
  非负整数 <span class="comment">固定值，位于 minBase~maxBase 之间</span>
</pre>

<h4 id="可用的地物">可用的地物</h4>
<p>这些是 Minecraft 内部已生成的地物命名空间ID，可直接使用。已省略 <code>minecraft:</code>。</p>
<pre>
<a href="vanilla/data/minecraft/worldgen/configured_feature/acacia.json">acacia</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/bamboo.json">bamboo</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/bamboo_light.json">bamboo_light</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/bamboo_vegetation.json">bamboo_vegetation</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/basalt_blobs.json">basalt_blobs</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/basalt_pillar.json">basalt_pillar</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/birch.json">birch</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/birch_bees_0002.json">birch_bees_0002</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/birch_bees_002.json">birch_bees_002</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/birch_bees_005.json">birch_bees_005</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/birch_other.json">birch_other</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/birch_tall.json">birch_tall</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/blackstone_blobs.json">blackstone_blobs</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/blue_ice.json">blue_ice</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/bonus_chest.json">bonus_chest</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/brown_mushroom_giant.json">brown_mushroom_giant</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/brown_mushroom_nether.json">brown_mushroom_nether</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/brown_mushroom_normal.json">brown_mushroom_normal</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/brown_mushroom_swamp.json">brown_mushroom_swamp</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/brown_mushroom_taiga.json">brown_mushroom_taiga</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/chorus_plant.json">chorus_plant</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/crimson_forest_vegetation.json">crimson_forest_vegetation</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/crimson_fungi.json">crimson_fungi</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/crimson_fungi_planted.json">crimson_fungi_planted</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/dark_forest_vegetation_brown.json">dark_forest_vegetation_brown</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/dark_forest_vegetation_red.json">dark_forest_vegetation_red</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/dark_oak.json">dark_oak</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/delta.json">delta</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/desert_well.json">desert_well</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/disk_clay.json">disk_clay</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/disk_gravel.json">disk_gravel</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/disk_sand.json">disk_sand</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/end_gateway.json">end_gateway</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/end_gateway_delayed.json">end_gateway_delayed</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/end_island.json">end_island</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/end_island_decorated.json">end_island_decorated</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/end_spike.json">end_spike</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/fancy_oak.json">fancy_oak</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/fancy_oak_bees_0002.json">fancy_oak_bees_0002</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/fancy_oak_bees_002.json">fancy_oak_bees_002</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/fancy_oak_bees_005.json">fancy_oak_bees_005</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/flower_default.json">flower_default</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/flower_forest.json">flower_forest</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/flower_plain.json">flower_plain</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/flower_plain_decorated.json">flower_plain_decorated</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/flower_swamp.json">flower_swamp</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/flower_warm.json">flower_warm</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/forest_flower_trees.json">forest_flower_trees</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/forest_flower_vegetation.json">forest_flower_vegetation</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/forest_flower_vegetation_common.json">forest_flower_vegetation_common</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/forest_rock.json">forest_rock</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/fossil.json">fossil</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/freeze_top_layer.json">freeze_top_layer</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/glowstone.json">glowstone</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/glowstone_extra.json">glowstone_extra</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/huge_brown_mushroom.json">huge_brown_mushroom</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/huge_red_mushroom.json">huge_red_mushroom</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/iceberg_blue.json">iceberg_blue</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/iceberg_packed.json">iceberg_packed</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ice_patch.json">ice_patch</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ice_spike.json">ice_spike</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/jungle_bush.json">jungle_bush</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/jungle_tree.json">jungle_tree</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/jungle_tree_no_vine.json">jungle_tree_no_vine</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/kelp_cold.json">kelp_cold</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/kelp_warm.json">kelp_warm</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/lake_lava.json">lake_lava</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/lake_water.json">lake_water</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/large_basalt_columns.json">large_basalt_columns</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/mega_jungle_tree.json">mega_jungle_tree</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/mega_pine.json">mega_pine</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/mega_spruce.json">mega_spruce</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/monster_room.json">monster_room</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/mushroom_field_vegetation.json">mushroom_field_vegetation</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/nether_sprouts.json">nether_sprouts</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/oak.json">oak</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/oak_badlands.json">oak_badlands</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/oak_bees_0002.json">oak_bees_0002</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/oak_bees_002.json">oak_bees_002</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/oak_bees_005.json">oak_bees_005</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_andesite.json">ore_andesite</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_blackstone.json">ore_blackstone</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_coal.json">ore_coal</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_debris_large.json">ore_debris_large</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_debris_small.json">ore_debris_small</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_diamond.json">ore_diamond</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_diorite.json">ore_diorite</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_dirt.json">ore_dirt</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_emerald.json">ore_emerald</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_gold.json">ore_gold</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_gold_deltas.json">ore_gold_deltas</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_gold_extra.json">ore_gold_extra</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_gold_nether.json">ore_gold_nether</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_granite.json">ore_granite</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_gravel.json">ore_gravel</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_gravel_nether.json">ore_gravel_nether</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_infested.json">ore_infested</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_iron.json">ore_iron</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_lapis.json">ore_lapis</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_magma.json">ore_magma</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_quartz_deltas.json">ore_quartz_deltas</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_quartz_nether.json">ore_quartz_nether</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_redstone.json">ore_redstone</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/ore_soul_sand.json">ore_soul_sand</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_berry_bush.json">patch_berry_bush</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_berry_decorated.json">patch_berry_decorated</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_berry_sparse.json">patch_berry_sparse</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_brown_mushroom.json">patch_brown_mushroom</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_cactus.json">patch_cactus</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_cactus_decorated.json">patch_cactus_decorated</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_cactus_desert.json">patch_cactus_desert</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_crimson_roots.json">patch_crimson_roots</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_dead_bush.json">patch_dead_bush</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_dead_bush_2.json">patch_dead_bush_2</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_dead_bush_badlands.json">patch_dead_bush_badlands</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_fire.json">patch_fire</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_grass_badlands.json">patch_grass_badlands</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_grass_forest.json">patch_grass_forest</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_grass_jungle.json">patch_grass_jungle</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_grass_normal.json">patch_grass_normal</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_grass_plain.json">patch_grass_plain</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_grass_savanna.json">patch_grass_savanna</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_grass_taiga.json">patch_grass_taiga</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_grass_taiga_2.json">patch_grass_taiga_2</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_large_fern.json">patch_large_fern</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_melon.json">patch_melon</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_pumpkin.json">patch_pumpkin</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_red_mushroom.json">patch_red_mushroom</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_soul_fire.json">patch_soul_fire</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_sugar_cane.json">patch_sugar_cane</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_sugar_cane_badlands.json">patch_sugar_cane_badlands</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_sugar_cane_desert.json">patch_sugar_cane_desert</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_sugar_cane_swamp.json">patch_sugar_cane_swamp</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_sunflower.json">patch_sunflower</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_taiga_grass.json">patch_taiga_grass</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_tall_grass.json">patch_tall_grass</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_tall_grass_2.json">patch_tall_grass_2</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/patch_waterlilly.json">patch_waterlilly</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/pile_hay.json">pile_hay</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/pile_ice.json">pile_ice</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/pile_melon.json">pile_melon</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/pile_pumpkin.json">pile_pumpkin</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/pile_snow.json">pile_snow</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/pine.json">pine</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/plain_vegetation.json">plain_vegetation</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/red_mushroom_giant.json">red_mushroom_giant</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/red_mushroom_nether.json">red_mushroom_nether</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/red_mushroom_normal.json">red_mushroom_normal</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/red_mushroom_swamp.json">red_mushroom_swamp</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/red_mushroom_taiga.json">red_mushroom_taiga</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/seagrass_cold.json">seagrass_cold</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/seagrass_deep.json">seagrass_deep</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/seagrass_deep_cold.json">seagrass_deep_cold</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/seagrass_deep_warm.json">seagrass_deep_warm</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/seagrass_normal.json">seagrass_normal</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/seagrass_river.json">seagrass_river</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/seagrass_simple.json">seagrass_simple</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/seagrass_swamp.json">seagrass_swamp</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/seagrass_warm.json">seagrass_warm</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/sea_pickle.json">sea_pickle</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/small_basalt_columns.json">small_basalt_columns</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/spring_closed.json">spring_closed</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/spring_closed_double.json">spring_closed_double</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/spring_delta.json">spring_delta</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/spring_lava.json">spring_lava</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/spring_lava_double.json">spring_lava_double</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/spring_open.json">spring_open</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/spring_water.json">spring_water</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/spruce.json">spruce</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/spruce_snowy.json">spruce_snowy</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/super_birch_bees_0002.json">super_birch_bees_0002</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/swamp_tree.json">swamp_tree</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/taiga_vegetation.json">taiga_vegetation</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/trees_birch.json">trees_birch</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/trees_giant.json">trees_giant</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/trees_giant_spruce.json">trees_giant_spruce</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/trees_jungle.json">trees_jungle</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/trees_jungle_edge.json">trees_jungle_edge</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/trees_mountain.json">trees_mountain</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/trees_mountain_edge.json">trees_mountain_edge</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/trees_savanna.json">trees_savanna</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/trees_shattered_savanna.json">trees_shattered_savanna</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/trees_water.json">trees_water</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/twisting_vines.json">twisting_vines</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/vines.json">vines</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/void_start_platform.json">void_start_platform</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/warm_ocean_vegetation.json">warm_ocean_vegetation</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/warped_forest_vegetation.json">warped_forest_vegetation</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/warped_fungi.json">warped_fungi</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/warped_fungi_planted.json">warped_fungi_planted</a>
<a href="vanilla/data/minecraft/worldgen/configured_feature/weeping_vines.json">weeping_vines</a>
</pre>

<h4 id="装饰物">装饰物</h4>
<pre class="file" id="装饰物JSON格式">装饰物JSON格式</pre>
<pre>
{
  "type": "minecraft:chance"<span class="comment">随机</span>, "lava_lake"<span class="comment">岩浆湖</span>, 或 "water_lake"<span class="comment">湖泊</span>
  "config": {
    "chance": 0~1 之间的数值 <span class="comment">生成几率</span>
  }
}
或
{
  "type": "minecraft:count"<span class="comment">生成的数量</span>, "fire"<span class="comment">火</span>, "glowstone"<span class="comment">荧石</span> 或 "count_multilayer"<span class="comment">多层数量</span>
  "config": {
    "count": <a href="#均匀分布的整数">均匀分布的整数</a> (minBase=-10, maxBase=128, maxSpread=128) <span class="comment">数量</span>
  }
}
或
{
  "type": "minecraft:count_noise", <span class="comment">生成的数量(噪声型)</span>
  "config": {
    "noise_level": 数值,
    "below_noise": 整数,
    "above_noise": 整数
  }
}
或
{
  "type": "minecraft:count_noise_biased", <span class="comment">生成的数量(带偏差的噪声型)</span>
  "config": {
    "noise_to_count_ratio": 整数,
    "noise_factor": 数值,
    "noise_offset": 数值, 默认为 0 <span class="comment">可选</span>
  }
}
或
{
  "type": "minecraft:count_extra", <span class="comment">生成的数量(带额外数量)</span>
  "config": {
    "count": 整数,
    "extra_chance": 数值,
    "extra_count": 整数
  }
}
或
{
  "type": "minecraft:range", "minecraft:range_biased" 或 "minecraft:range_very_biased", <span class="comment">区间数值(无偏好、带偏好、带强烈偏好)</span>
  "config": {
    "bottom_offset": 整数, 默认为 0, <span class="comment">可选</span>
    "top_offset": 整数, 默认为 0, <span class="comment">可选</span>
    "maximum": 整数, 默认为 0 <span class="comment">可选</span>
  }
}
或
{
  "type": "minecraft:depth_average", <span class="comment">TBD</span>
  "config": {
    "baseline": 整数,
    "spread": 整数
  }
}
或
{
  "type": "minecraft:carving_mask", <span class="comment">TBD</span>
  "config": {
    "step": "air" 或 "liquid", <span class="comment">雕刻器生成阶段</span>
    "probability": 0~1 之间的数值 <span class="comment">几率</span>
  }
}
或
{
  "type": "minecraft:decorated, <span class="comment">TBD</span>
  "config": {
    "outer": "<a href="#装饰物">装饰物</a>命名空间ID" 或 <a href="#装饰物">装饰物</a>JSON对象, <span class="comment">TBD，外部装饰物</span>
    "inner": "<a href="#装饰物">装饰物</a>命名空间ID" 或 <a href="#装饰物">装饰物</a>JSON对象 <span class="comment">TBD，内部装饰物</span>
  }
}
</pre>

<h4 id="可用的装饰物">可用的装饰物</h4>
<p>这些是 Minecraft 内部已生成的装饰物命名空间ID，可直接使用。已省略 <code>minecraft:</code>。</p>
<pre>
nope
square
heightmap
heightmap_spread_double
top_solid_heightmap
heightmap_world_surface
spread_32_above
magma
emerald_ore
end_gateway
dark_oak_tree
iceberg
end_island
chance
lava_lake
water_lake
count
fire
glowstone
count_multilayer
count_noise
count_noise_biased
count_extra
range
range_biased
range_very_biased
depth_average
carving_mask
decorated
</pre>

<h3 id="结构地物">§2.12.6 结构地物</h3>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/worldgen‌/configured_structure_feature/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/自定义世界生成#结构地物" class="wiki">结构地物</a></li>
  <li><a href="https://minecraft.wiki/w/Configured_structure_feature" class="wikien">Configured structure feature</a></li>
</ul>

<p>结构地物 (Structure feature) 指定特定类型的结构以及结构的参数，被调用于<a href="#生物群系">生物群系</a>JSON文件的 <code>starts</code>。</p>

<pre class="file" id="结构地物JSON格式">结构地物JSON格式</pre>
<pre>
{
  "type": "minecraft:pillager_outpost"<span class="comment">掠夺者前哨站</span>, "minecraft:village"<span class="comment">村庄</span> 或 "minecraft:bastion_remnant"<span class="comment">堡垒遗迹</span>
  "config": {
    "start_pool": "<a href="#模板池">模板池</a>命名空间ID",
    "size": 0~7 之间的整数 <span class="comment">TBD</span>
  }
}
或
{
  "type": "minecraft:mineshaft"<span class="comment">矿井</span>,
  "config": {
    "type": "normal"<span class="comment">普通</span> 或 "mesa"<span class="comment">平顶山</span>
    "probability": 0~1 之间的数值 <span class="comment">几率</span>
  }
}
或
{
  "type": "minecraft:ruined_portal"<span class="comment">废弃传送门</span>,
  "config": {
    "portal_type"<span class="comment">类型</span>: "standard"<span class="comment">标准</span>, "desert"<span class="comment">沙漠</span>, "jungle"<span class="comment">丛林</span>, "swamp"<span class="comment">沼泽</span>, "mountain"<span class="comment">山地</span>, "ocean"<span class="comment">海洋</span> 或 "nether"<span class="comment">下界</span>
  }
}
或
{
  "type": "minecraft:shipwreck"<span class="comment">沉船</span>,
  "config": {
    "is_beached": true 或 false (默认值)<span class="comment">可选，是否搁浅</span>
  }
}
或
{
  "type": "minecraft:ocean_ruin"<span class="comment">海底废墟</span>,
  "config": {
    "biome_temp"<span class="comment">生物群系温度</span>: "warm"<span class="comment">暖水</span> 或 "cold"<span class="comment">冷水</span>
    "large_probability": 0~1 之间的数值, <span class="comment">几率</span>
    "cluster_probability": 0~1 之间的数值 <span class="comment">成群的几率</span>
  }
}
或
{
  "type": "minecraft:buried_treasure"<span class="comment">被掩埋的宝藏</span>,
  "config": {
    "probability": 0~1 之间的数值 <span class="comment">几率</span>
  }
}</pre>

<h4 id="可用的结构地物">可用的结构地物</h4>
<p>这些是 Minecraft 内部已生成的结构地物命名空间ID，可直接使用。已省略 <code>minecraft:</code>。</p>
<pre>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/bastion_remnant.json">bastion_remnant</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/buried_treasure.json">buried_treasure</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/desert_pyramid.json">desert_pyramid</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/end_city.json">end_city</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/fortress.json">fortress</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/igloo.json">igloo</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/jungle_pyramid.json">jungle_pyramid</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/mansion.json">mansion</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/mineshaft.json">mineshaft</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/mineshaft_mesa.json">mineshaft_mesa</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/monument.json">monument</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/nether_fossil.json">nether_fossil</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/ocean_ruin_cold.json">ocean_ruin_cold</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/ocean_ruin_warm.json">ocean_ruin_warm</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/pillager_outpost.json">pillager_outpost</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/ruined_portal.json">ruined_portal</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/ruined_portal_desert.json">ruined_portal_desert</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/ruined_portal_jungle.json">ruined_portal_jungle</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/ruined_portal_mountain.json">ruined_portal_mountain</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/ruined_portal_nether.json">ruined_portal_nether</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/ruined_portal_ocean.json">ruined_portal_ocean</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/ruined_portal_swamp.json">ruined_portal_swamp</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/shipwreck.json">shipwreck</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/shipwreck_beached.json">shipwreck_beached</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/stronghold.json">stronghold</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/swamp_hut.json">swamp_hut</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/village_desert.json">village_desert</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/village_plains.json">village_plains</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/village_savanna.json">village_savanna</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/village_snowy.json">village_snowy</a>
<a href="vanilla/data/minecraft/worldgen/configured_structure_feature/village_taiga.json">village_taiga</a>
</pre>


<h3 id="模板池">§2.12.8 模板池</h3>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/worldgen‌/template_pool/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/拼图方块" class="wiki">拼图方块</a></li>
  <li><a href="https://zh.minecraft.wiki/w/自定义世界生成#模板池" class="wiki">模板池</a></li>
  <li><a href="https://minecraft.wiki/w/Custom_world_generation#Jigsaw_pools" class="wikien">Jigsaw pools</a></li>
  <li><a href="https://www.mcbbs.net/thread-1093331-1-1.html">拼图方块与模板池教程</a></li>
  <li><a href="https://www.bilibili.com/video/BV1Vf4y1d7f7">1.16.2pre1支持自定义拼图方块系统</a></li>
</ul>

<p>模板池 (Template pool) 使用结构文件来生成结构，其中结构包含的拼图方块会工作以生成更复杂的结构。拼图方块是一个允许游戏使用较小模板生成结构的拼接方块：</p>
<ul>
  <li><code>name</code> 名称，该拼图方块的标记。</li>
  <li><code>pool</code> 目标池，指的是拼图方块将要使用的模板池。</li>
  <li><code>target</code> 目标，与该拼图方块连接的另一拼图方块的 <code>name</code>。</li>
  <li><code>joint</code> 连接类型，<code>rollable</code> (默认值) 或 <code>aligned</code>。当拼图方块朝上或朝下时才有，其中 <code>aligned</code> 指拼接的结构位置固定，<code>rollable</code> 指的是拼接的结构可随机旋转。</li>
  <li><code>final_state</code> 转变为：指的是拼图方块在整个功能被放置后会转变的方块。默认为 <code>minecraft:air</code>。</li>
  <li>层数，<code>0~7</code> 之间，指生成完之后拼接的结构继续生成的嵌套层数。</li>
  <li>保留拼图方块，与其拼接的结构生成完之后其包含的拼图方块保留还是转变为 <code>final_state</code> 指定方块。</li>
</ul>
<p>拼图方块目前仅用于生成掠夺者前哨站、村庄和堡垒遗迹类型的结构地物。这些结构的生成开始于包含拼图方块的模板。每个拼图方块都使用下列流程来生成另一个模板：</p>
<ul>
  <li>在目标池内随机选择一个模板。</li>
  <li>在该模板的拼图方块，至少存在1个模板含有目标拼图方块。如果有多个方块符合条件，那么会随机选择其中的一个。</li>
  <li>这会使两个拼图方块连接使得第2个拼图方块朝向第1个拼图方块并与之相邻。</li>
  <li>最后，两个拼图方块会被替换为对应的“转变方块”设置的方块。</li>
</ul>
<p class="noindent">初始模板和附加模板里的拼图方块都会重复上述流程，直到没有剩余的拼图方块或者结构足够大为止。使用结构方块加载结构不能复现上述过程。</p>

<pre class="file" id="模板池JSON格式">模板池JSON格式</pre>
<pre>
{
  "name": "命名空间ID", <span class="comment">该随机池的名称，用于拼图方块调用</span>
  "fallback": "<a href="#模板池">模板池</a>命名空间ID", <span class="comment">结构生成完毕且无法再尝试生成时，可连接另一个模板池继续生成</span>
  "elements": [ <span class="comment">结构列表</span>
    {
      "weight": 整数, <span class="comment">权重</span>
      "element": {
        "location": "<a href="#结构">结构文件</a>命名空间ID",
        "projection": "rigid" <span class="comment">直接生成相应结构</span> 或 "terrain_matching", <span class="comment">调整地形或结构来与地形匹配</span>
        "element_type": "minecraft:empty_pool_element"<span class="comment">不生成任何结构</span>, "minecaft:list_pool_element"<span class="comment">生成一个地形</span>, "minecraft:legacy_single_pool_element"<span class="comment">  只使用location中的结构，使这整个元素变为残骸元素池</span> 或 "minecraft:single_pool_element", <span class="comment">只使用location中的结构，使这整个元素变为单元素池</span>
        "processors": "<a href="#处理器列表">处理器列表</a>命名空间ID",
        "elements": [ <span class="comment">除了 empty_pool_element 以外均需该标签，格式与上一级标签相同</span>
        ]
      }
    }
  ]
}</pre>

<h3 id="处理器列表">§2.12.9 处理器列表</h3>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/worldgen‌/processor_list/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/自定义世界生成#处理器列表" class="wiki">处理器列表</a></li>
  <li><a href="https://minecraft.wiki/w/Custom_world_generation#Processor_lists" class="wikien">Processor lists</a></li>
</ul>
<p>处理器列表 (Processor list) 用于指定拼图方块生成结构之后拼图方块本身的处理方式。</p>

<pre class="file" id="处理器列表JSON格式">处理器列表JSON格式</pre>
<pre>
{
  "processors": [ <span class="comment">处理器列表</span>
    {
      "processor_type": "minecraft:rule",
      "rules": [ <span class="comment">规则列表</span>
        {
          "position_predicate": <a href="#方块处理条件">方块处理条件</a>JSON对象, <span class="comment">结构生成前当前位置方块</span>
          "input_predicate": <a href="#方块处理条件">方块处理条件</a>JSON对象, <span class="comment">结构种当前位置方块</span>
          "location_predicate": <a href="#方块处理条件">方块处理条件</a>JSON对象, <span class="comment">结构生成前的方块处理条件</span>
          "output_state": { <span class="comment">条件满足时放置的方块</span>
            "Name": "方块命名空间ID",
            "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
              "方块状态名": "方块状态值"
            }
          }
        }
      ]
    或
      "processor_type": "minecraft:block_rot", <span class="comment">随机移除方块</span>
      "integrity": 0~1 之间的数值 <span class="comment">几率</span>
    或
      "processor_type": "minecraft:protected_blocks", <span class="comment">保护相应标签的方块不被结构所替换</span>
      "value": <a href="#方块标签">方块标签</a>命名空间ID
    }
  ]
}</pre>

<pre class="file" id="方块处理条件">方块处理条件JSON对象</pre>
<pre>
{
  "predicate_type": "always_true" <span class="comment">总是成立</span>
}
或
{
  "predicate_type": "axis_aligned_linear_pos", <span class="comment">根据相应轴的方块距离结构初始位置的距离来线性插值通过几率</span>
  "axis": "x", "y" 或 "z", <span class="comment">计算哪条轴的距离</span>
  "min_dist": 正整数, <span class="comment">方块距离结构初始位置的最短距离</span>
  "max_dist": 正整数, <span class="comment">方块距离结构初始位置的最远距离</span>
  "min_chance": 0~1 之间的数值, <span class="comment">当方块距离结构初始位置为 min_dist 时该断言通过几率</span>
  "max_chance": 0~1 之间的数值, <span class="comment">当方块距离结构初始位置为 max_dist 时该断言通过几率，介于 min_dist 和 max_dist 之间的则线性插值</span>
}
或
{
  "predicate_type": "block_match", <span class="comment">匹配方块</span>
  "block": "方块命名空间ID"
}
或
{
  "predicate_type": "blockstate_match", <span class="comment">匹配方块状态</span>
  "block_state": {
    "Name": "方块命名空间ID",
    "Properties": { <span class="comment">需要指定该方块的所有方块状态</span>
      "方块状态名": "方块状态值"
    }
  }
}
或
{
  "predicate_type": "random_block_match", <span class="comment">随机方块匹配</span>
  "block": "方块命名空间ID"
  "probability": 0~1 之间的数值, <span class="comment">方块匹配时的通过几率</span>
}
或
{
  "predicate_type": "tag_match", <span class="comment">匹配方块标签</span>
  "tag": "<a href="#方块标签">方块标签</a>命名空间ID"
}
</pre>

<h4 id="可用的处理器列表">可用的处理器列表</h4>
<p>这些是 Minecraft 内部已生成的处理器列表命名空间ID，可直接使用。已省略 <code>minecraft:</code>。</p>
<pre>
<a href="vanilla/data/minecraft/worldgen/processor_list/bastion_generic_degradation.json">bastion_generic_degradation</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/bottom_rampart.json">bottom_rampart</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/bridge.json">bridge</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/empty.json">empty</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/entrance_replacement.json">entrance_replacement</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/farm_desert.json">farm_desert</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/farm_plains.json">farm_plains</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/farm_savanna.json">farm_savanna</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/farm_snowy.json">farm_snowy</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/farm_taiga.json">farm_taiga</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/high_rampart.json">high_rampart</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/high_wall.json">high_wall</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/housing.json">housing</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/mossify_10_percent.json">mossify_10_percent</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/mossify_20_percent.json">mossify_20_percent</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/mossify_70_percent.json">mossify_70_percent</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/rampart_degradation.json">rampart_degradation</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/outpost_rot.json">outpost_rot</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/roof.json">roof</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/side_wall_degradation.json">side_wall_degradation</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/stable_degradation.json">stable_degradation</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/street_plains.json">street_plains</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/street_savanna.json">street_savanna</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/street_snowy_or_taiga.json">street_snowy_or_taiga</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/treasure_rooms.json">treasure_rooms</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/zombie_desert.json">zombie_desert</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/zombie_plains.json">zombie_plains</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/zombie_savanna.json">zombie_savanna</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/zombie_snowy.json">zombie_snowy</a>
<a href="vanilla/data/minecraft/worldgen/processor_list/zombie_taiga.json">zombie_taiga</a>
</pre>




<h1 id="资源包">§3 资源包</h1>
<p>参考<a href="https://zh.minecraft.wiki/w/资源包">资源包</a>，<a href="https://zh.minecraft.wiki/w/教程/制作资源包" class="wiki">教程/制作资源包</a>。资源包 (resourcepacks) 可以极大地提升原版模组的美观程度，因此现在大部分原版模组都需要使用配套的资源包。资源包文件层次为</p>
<pre class="file">resourcepacks/<i>资源包名称</i>或<i>资源包名称</i>.zip/</pre>
<pre>
pack.mcmeta
pack.png
assets
  命名空间
    lang
      zh_cn.json
      zh_tw.json
      en_us.json
      <i>其它语言</i>.json
    blockstates
      <i>方块状态</i>.json
    models
      <i>模型</i>.json
    textures
      <i>方块状态</i>.json
    font
      <i>字体</i>.json
    sounds.json
    sounds
      <i>声音</i>.ogg
    particles
      <i>颗粒</i>.json
    shaders
      post
        <i>后处理着色器渲染管线</i>.json
      program
        <i>着色器程序</i>.json
        <i>顶点着色器</i>.vsh
        <i>片段着色器</i>.fsh
      core
        <i>核心着色器程序</i>.json
        <i>顶点着色器</i>.vsh
        <i>片段着色器</i>.fsh
    texts
      <i>文本</i>.txt
</pre>
<p class="noindent">其中 <code>assets</code> 的文件结构和 <a href="#游戏文件结构">§1.3.1 游戏文件结构</a>中 <code>versions/<i>版本号</i>/<i>版本号</i>.jar/assets</code> 的结构是一样的。</p>
<p><code>assets</code> 下所有文件和文件夹需使用小写英文、数字或-(折线)，_(下划线)，.(点)来命名，<strong>不可使用大写字母</strong>，所有文本文件为使用 <code>UTF-8</code> 编码的JSON文件，图片为 <code>png</code> 格式。资源包可以为文件夹格式或 zip 格式，发布时可将所有内容压缩为一个 zip 文件。压缩和解压的时候，注意文件层次，应当打开 zip 文件就可以看到资源包的 pack.mcmeta、pack.png 和 assets 文件夹。稳妥的做法是<code>打开文件夹->全选->右键->发送到->压缩文件夹</code>。文件夹格式的资源包若有错误文件仍可以加载，但 <code>zip</code> 格式的会无法加载。</p>
<p>游戏内选择<code>选项->资源包</code>可以列出所有的资源包。在资源包菜单中，加载次序由下至上，因此上方的资源包内容会覆盖下方的资源包同名内容。由于原版模组往往会修改原版物品自定义模型，因此同时安装多个原版模组的资源包时，很容易出现文件冲突，此时需要玩家手动合并资源包方可使用。具体而言，对比两个资源包的同名文件，将相同的模型文件的 <code>overrides</code> 合并，其它内容选择需要的留下即可。</p>
<p>若资源包位于 <code>saves/<i>世界名称</i>/resources.zip</code>，则资源包会在进入存档时自动加载(最顶层)。</p>
<p>本节中我们仅对资源包做简单介绍，更详细的文件说明请参阅<a href="https://zh.minecraft.wiki/w/资源包">资源包 - Minecraft Wiki，最详细的官方我的世界百科</a>或论坛纹理资源版相关内容。</p>
<p>纹理包和资源包是不同的东西，目前 Minecraft Java 只有资源包，请不要使用错误的名称。</p>

<h2 id="资源包/元信息和图标">§3.1 元信息和图标</h2>

<p>Minecraft 通过文件 <code>pack.mcmeta</code> 来识别资源包，因此该文件是不可或缺的。例如：</p>
<pre class="file">pack.mcmeta</pre>
<pre>
{
  "pack": {
    "pack_format": 6, <span class="comment">资源包版本，1.13-1.14 版本为 4，1.15 版本为 5，1.16.2-1.16.5 版本为 6，1.17-1.17.1 版本为 7，1.18–1.18.2 版本为8，1.19 版本为9</span>
    "description": [ <span class="comment">资源包描述</span>
      {
        "text": "Crafting++ v1.10 ",
        "color": "gold"
      },
      {
        "translate": "options.resourcepack"
      },
      {
        "text": "\nruhuasiyu RubberTree",
        "color": "green"
      }
    ]
  },
  "filter": {
    "block": [<span class="comment">忽略相应命名空间下相应文件</span>
      {
        "namespace": "命名空间", 
        "path": "文件路径" <span class="comment">支持通用标识符 *</span>
      }
    ]
  }
}    
</pre>

<p class="noindent">其中资源包描述为单个字符串或一个<a href="https://zh.minecraft.wiki/w/命令#.E5.8E.9F.E5.A7.8BJSON.E6.96.87.E6.9C.AC">原始JSON文本</a>。在资源包菜单页面，它会显示在资源包名称下方。</p>

<p>原版资源包里的 <code>pack.mcmeta</code> 文件为</p>
<pre class="file">pack.mcmeta</pre>
<pre>
{
    "pack": {
        "pack_format": 6,
        "description": "The default data for Minecraft"
    }
}
</pre>

<p>资源包可以包含一个 <a href="vanilla/pack.png"><code>pack.png</code></a>，它是正方形的图片，用于在资源包菜单中显示。</p>

<h2 id="资源包/命名空间">§3.2 命名空间</h2>
<p>命名空间 (Namespace) 为玩家自定义的、可操作的空间。使用独立的命名空间也有利于解决和他人的冲突。资源包下可以有多个命名空间，如果不同资源包中有相同的命名空间，则其中相同的文件名内容会根据加载先后顺序被覆盖。特别地，原版内容被保存在 <code>minecraft</code> 命名空间，想要修改和替换原版的模型纹理只需在你的资源包内建立 <code>minecraft</code> 命名空间和相应的同名文件并修改即可。</p>


<table><thead><tr><th>类型</th><th>调用格式(命名空间ID)</th><th>文件路径</th></tr></thead><tbody>
<tr>
  <th>模型</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/models/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>纹理</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/textures/<i>路径</i>/<i>文件名</i>.png</code></td>
</tr>
<tr>
  <th>字体</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/font/<i>路径</i>/<i>文件名</i>.json</code></td>
</tr>
<tr>
  <th>声音</th>
  <td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td>
  <td><code><i>命名空间</i>/sounds/<i>路径</i>/<i>文件名</i>.ogg</code></td>
</tr>
</tbody></table>

<p>若命名空间为 <code>minecraft</code>，则可直接省略 <code>minecraft:</code>。</p>
<p>建议和数据包使用相同的命名空间名。</p>

<h2 id="语言文件">§3.3 语言文件</h2>
<table><tbody>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/lang/<i>语言代码</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/资源包#语言" class="wiki">语言</a></li>
  <li><a href="https://minecraft.wiki/w/Resource_Pack#Language" class="wikien">Language</a></li>
</ul>

<p>语言文件 (Lang) 可以放在任一命名空间下的 <code>lang</code> 文件夹下。原版的语言文件除了 <code>en_us.json</code> 位于原版资源包外，其它的语言文件位于<a href="#资源文件">资源文件夹</a>下。</p>
<p>语言文件中可以使用样式代码来实现彩色文字，但我们更建议使用<a href="#原始JSON文本格式">原始JSON文本</a>来实现，以避免在铁砧上重命名时出现多余的字符。建议至少支持简体中文(<code>zh_cn</code>)、繁体中文(<code>zh_tw</code>)和英文(<code>en_us</code>)三种语言，建议所有物品、进度、游戏提示等文本均采用 <code>translate</code> 文本。</p>
<pre class="file">assets/custom/lang/zh_cn.json</pre>
<pre>
{
  "item.ex.magnet":"磁铁",
  ...
}
</pre>
<pre class="file">assets/custom/lang/en_us.json</pre>
<pre>
{
  "item.ex.magnet":"Magnet",
  ...
}
</pre>

<p>也可以用此方法修改物品的默认名称等内容。例如：</p>
<pre class="file">assets/custom/lang/zh_cn.json</pre>
<pre>
{
  "item.minecraft.potion.effect.empty": "神秘药水",
  ...
}
</pre>
<p class="noindent">则未知的药水的名称不再是<code>不可合成的药水</code>，而是<code>神秘药水</code>。</p>

<p><code>translate</code> 还有个有趣但不一定实用的用法。</p>
<pre class="file">assets/custom/lang/zh_cn.json</pre>
<pre>
{
  "The":"原版模组《更多的合成》已成功加载,",      
  "resourcepack":"版本",
  "does":"1.9.1a.",
  "not":"更多内容请",
  "Install":"点击此处进入wiki.",
  "correctly":"作者:",
  "or":"ruhuasiyu,",
  "Launch":"RubberTree",
  ...
}
</pre>
<p class="noindent">则在数据包中输出相应文本时，若无资源包或资源包错误，则会显示 <code>The resourcepack does not Installl correctly or Launch</code> 以提示玩家资源包未加载。</p>

<h2 id="自定义物品模型">§3.4 自定义物品模型</h2>
<p>由于1.14添加了 <code>CustomModelData</code>，我们可以拥有几乎无穷多的物品模型。为了便于他人整合和解决冲突，建议将 <code>CustomModelData</code> 的前四位固定以确定模组的独有区段，后四位作为模组不同模型的值，例如 <code>12340000-12349999</code> 之间。此外，建议 <code>CustomModelData</code> 不要超过 <code>16777216</code>，原因见 <a href="https://www.mcbbs.net/thread-867051-1-1.html">custom_model_data 的使用限制</a>。</p>

<p>我们会给出一个例子来说明实现流程。首先在 <code>minecraft</code> 下的胡萝卜钓竿物品模型中添加额外的模型 (<code>overrides</code>)，并引用我们自定义的模型。</p>
<pre class="file" id="assets/minecraft/models/item/carrot_on_a_stick">assets/minecraft/models/item/carrot_on_a_stick.json</pre>
<pre>
{
  "parent": "item/handheld_rod",
  "textures": {
    "layer0": "item/carrot_on_a_stick"
  },
  "overrides": [
    { "predicate": { "custom_model_data": 12970001 }, "model": "cpp:element/blue_force_of_sky"},
    { "predicate": { "custom_model_data": 12970002 }, "model": "cpp:element/green_force_of_water"},
    { "predicate": { "custom_model_data": 12970003 }, "model": "cpp:element/cyan_force_of_mountain"},
    { "predicate": { "custom_model_data": 12970004 }, "model": "cpp:element/orange_force_of_dirt"},
    { "predicate": { "custom_model_data": 12970005 }, "model": "cpp:element/yellow_force_of_earth"},
    { "predicate": { "custom_model_data": 12970006 }, "model": "cpp:element/red_force_of_fire"}
  ]
}
</pre>
<p class="noindent">注意 <code>custom_model_data</code> 需要按照从小往大的次序，否则会导致后面的覆盖前面的。然后创建自定义的模型</p>
<pre class="file" id="assets/cpp/models/element/red_force_of_fire">assets/cpp/models/element/red_force_of_fire.json</pre>
<pre>
{
  "parent": "item/handheld",
  "textures": {
    "layer0": "cpp:element/red_force_of_fire"
  }
}
</pre>
<p class="noindent">最后绘制纹理，并将其保存为 <code>assets/craftingpp/textures/element/red_force_of_fire.png</code>。这样我们就设计好了这个物品模型，在 <a href="#物品设计">§5 物品设计</a>我们将会说明如何使用该模型。</p>

<h2 id="模型">§3.5 模型</h2>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/models/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/模型" class="wiki">模型</a></li>
  <li><a href="https://minecraft.wiki/w/Models" class="wikien">Models</a></li>
</ul>
<p>模型 (Model) 是一个描述形状和指定纹理的JSON文件。模型可以理解成一些可以旋转的长方体的拼接，每个长方体的若干个面贴上了纹理图案。长方体的厚度可以为0，也可以只有若干个面。</p>
<p>只有 <code>minecraft</code> 命名空间下特定名称的文件才对应特定的物品/方块模型，例如 <code>minecraft/models/item/carrot_on_a_stick.json</code> 表示胡萝卜钓竿的物品模型，<code>minecraft/models/block/stone.json</code> 表示石头的方块模型。</p>
<p>我们通过几个例子来理解下模型文件的语法。</p>
<pre class="file" id="minecraft/models/item/handheld">minecraft/models/item/handheld.json</pre>
<pre>
{
  "parent": "item/generated",
  "display": {
    "thirdperson_righthand": {
      "rotation": [ 0, -90, 55 ],
      "translation": [ 0, 4.0, 0.5 ],
      "scale": [ 0.85, 0.85, 0.85 ]
    },
    "thirdperson_lefthand": {
      "rotation": [ 0, 90, -55 ],
      "translation": [ 0, 4.0, 0.5 ],
      "scale": [ 0.85, 0.85, 0.85 ]
    },
    "firstperson_righthand": {
      "rotation": [ 0, -90, 25 ],
      "translation": [ 1.13, 3.2, 1.13 ],
      "scale": [ 0.68, 0.68, 0.68 ]
    },
    "firstperson_lefthand": {
      "rotation": [ 0, 90, -25 ],
      "translation": [ 1.13, 3.2, 1.13 ],
      "scale": [ 0.68, 0.68, 0.68 ]
    }
  }
}
</pre>
<pre class="file" id="cpp/models/head/rabbit">cpp/models/head/rabbit.json</pre>
<pre>
{
  "parent": "block/block",
  "gui_light": "side",
  "elements": [
    {
      "from": [ 5.5, 6, 5.5 ],
      "to": [ 10.5, 10, 10.5 ],
      "faces": {
        "east":    { "uv": [ 8, 2.5, 9.25, 4.5 ], "texture": "#layer" },
        "north":{ "uv": [ 9.25, 2.5, 10.5, 4.5 ], "texture": "#layer"},
        "west":    { "uv": [ 10.5, 2.5, 11.75, 4.5 ], "texture": "#layer" },
        "south":{ "uv": [ 11.75, 2.5, 13, 4.5 ], "texture": "#layer" },
        "up":    { "uv": [ 9.25, 0, 10.5, 2.5 ], "texture": "#layer", "rotation": 180},
        "down":    { "uv": [ 10.5, 0, 11.75, 2.5 ], "texture": "#layer" }
      }
    },
    {
      "from": [ 7.5, 7.5, 5 ],
      "to": [ 8.5, 8.5, 6 ],
      "faces": {
        "east":    { "uv": [ 8, 5, 8.25, 5.5 ], "texture": "#layer" },
        "north":{ "uv": [ 8.25, 5, 8.5, 5.5 ], "texture": "#layer"},
        "west":    { "uv": [ 8.5, 5, 8.75, 5.5 ], "texture": "#layer" },
        "south":{ "uv": [ 8.75, 5, 9, 5.5 ], "texture": "#layer" },
        "up":    { "uv": [ 8.25, 4.5, 8.5, 5 ], "texture": "#layer", "rotation": 180},
        "down":    { "uv": [ 8.5, 4.5, 8.75, 5 ], "texture": "#layer" }
      }
    },
    {
      "from": [ 5.5, 10, 9.5 ],
      "to": [ 7.5, 15, 10.5 ],
      "rotation": {
        "origin": [6.5, 10, 10], "axis": "y", "angle": -22.5
      },
      "faces": {
        "east":    { "uv": [ 14.5, 0.5, 14.75, 3 ], "texture": "#layer" },
        "north":{ "uv": [ 14.75, 0.5, 15.25, 3 ], "texture": "#layer"},
        "west":    { "uv": [ 15.25, 0.5, 15.5, 3 ], "texture": "#layer" },
        "south":{ "uv": [ 15.5, 0.5, 16, 3 ], "texture": "#layer" },
        "up":    { "uv": [ 14.75, 0, 15.25, 0.5 ], "texture": "#layer", "rotation": 180},
        "down":    { "uv": [ 15.25, 0, 15.75, 0.5 ], "texture": "#layer" }
      }
    },
    {
      "from": [ 8.5, 10, 9.5 ],
      "to": [ 10.5, 15, 10.5 ],
      "rotation": {
        "origin": [9.5, 10, 10], "axis": "y", "angle": 22.5
      },
      "faces": {
        "east":    { "uv": [ 13, 0.5, 13.25, 3 ], "texture": "#layer" },
        "north":{ "uv": [ 13.25, 0.5, 13.75, 3 ], "texture": "#layer"},
        "west":    { "uv": [ 13.75, 0.5, 14, 3 ], "texture": "#layer" },
        "south":{ "uv": [ 14, 0.5, 14.5, 3 ], "texture": "#layer" },
        "up":    { "uv": [ 13.25, 0, 13.75, 0.5 ], "texture": "#layer", "rotation": 180},
        "down":    { "uv": [ 13.75, 0, 14.25, 0.5 ], "texture": "#layer" }
      }
    }
  ],
  "display": {
    "head": {
      "scale": [ 3.28, 3.28, 3.28 ]
    },
    "gui": {
      "rotation": [ 30, 225, 0 ],
      "translation": [0, -2, 0],
      "scale": [ 1.6, 1.6, 1.6 ]
    },
    "ground": {
      "rotation": [ 0, 0, 0 ],
      "translation": [ 0, 3, 0],
      "scale":[ 0.64, 0.64, 0.64 ]
    },
    "fixed": {
      "rotation": [ 0, 0, 0 ],
      "translation": [ 0, 0, 0],
      "scale":[ 1.28, 1.28, 1.28 ]
    },
    "thirdperson_righthand": {
      "rotation": [ 75, 45, 0 ],
      "translation": [ 0, 2.5, 0],
      "scale": [ 0.96, 0.96, 0.96 ]
    },
    "firstperson_righthand": {
      "rotation": [ 0, 45, 0 ],
      "translation": [ 0, 0, 0 ],
      "scale": [ 1.02, 1.02, 1.02 ]
    },
    "firstperson_lefthand": {
      "rotation": [ 0, 225, 0 ],
      "translation": [ 0, 0, 0 ],
      "scale": [ 1.02, 1.02, 1.02 ]
    }
  },
  "textures": {
    "particle": "entity/rabbit/brown",
    "layer": "entity/rabbit/brown"
  }
}
</pre>

<table><thead><tr><th style="width:6em;">含义</th><th style="width:15em;">键</th><th>说明</th></tr></thead><tbody>
<tr>
  <th>父模型</th>
  <td><code>parent</code></td>
  <td>继承指定位置的模型内容，相当于将其文件内容复制到该位置，可以缺省。Minecraft 已经定义了很多常见模型，我们可以直接调用而无需自己编写。对于自定义的多个类似的模型，我们也可以写好一个模板后继承之。常见的默认模型有<ul>
      <li><code>minecraft:item/generated</code> 普通手持物，指定了手持物在不同位置的显示效果。</li>
      <li><code>minecraft:item/handheld</code> 手持工具物，与上一条有不同的旋转效果。</li>
      <li><code>minecraft:block/block</code> 方块，指定了方块在不同位置的显示效果。</li>
      <li><code>minecraft:block/cube</code> 完整方块，指定了一个1×1×1大小的方块模型。</li>
    </ul></td>
</tr>
<tr>
  <th>光照</th>
  <td><code>gui_light</code></td>
  <td>1.15.2版本起，表示光照方向，分为side(从左上背面打光)和front(从正面打光)。错误的选择会导致模型显得非常的暗。</td>
</tr>
<tr>
  <th>显示</th>
  <td><code>display</code></td>
  <td>物品在不同位置的显示效果。</td>
</tr>
<tr>
  <th>掉落物显示</th>
  <td><code>display.ground</code></td>
  <td>物品作为掉落物的显示效果。</td>
</tr>
<tr>
  <th>头部显示</th>
  <td><code>display.head</code></td>
  <td>物品佩戴在生物头部的显示效果。</td>
</tr>
<tr>
  <th>手持物显示</th>
  <td><code>display.firstperson_lefthand</code><br/>
    <code>display.firstperson_righthand</code><br/>
    <code>display.thirdperson_lefthand</code><br/>
    <code>display.thirdperson_righthand</code>
  </td>
  <td>物品在第一人称左手、第一人称右手、第三人称左手、第三人称右手的显示效果。</td>
</tr>
<tr>
  <th>展示框显示</th>
  <td><code>display.fixed</code></td>
  <td>物品在物品展示框内的显示效果。</td>
</tr>
<tr>
  <th>展示框显示</th>
  <td><code>display.gui</code></td>
  <td>物品在玩家背包或容器内的显示效果。</td>
</tr>
<tr>
  <th>变换</th>
  <td><code>display.[位置].scale</code><br/>
    <code>display.[位置].translation</code><br/>
    <code>display.[位置].rotation</code>
  </td>
  <td>物品在相应位置进行的放缩、平移和旋转。至多放缩至4倍，平移至±80。</td>
</tr>
<tr>
  <th>元素</th>
  <td><code>elements</code></td>
  <td>列表的每个项确定一个长方体。</td>
</tr>
<tr>
  <th>元素范围</th>
  <td><code>elements.from</code><br/>
    <code>elements.to</code></td>
  <td>确定元素的范围。其三个坐标xyz范围为-16到32之间，不做放缩时，0~16即一个方块的完整大小。放置方块后，方块的x轴从右往左，y轴从下往上，z轴从近往远。在背包或展示框中时，x轴从左往右，y轴从上往下，z轴从远往近。</td>
</tr>
<tr>
  <th>元素旋转</th>
  <td><code>rotation.origin</code><br/>
    <code>rotation.axis</code><br/>
    <code>rotation.angle</code></td>
  <td>将元素进行旋转，分别表示旋转中心、旋转的坐标轴、旋转的角度。其中角度只能是<code>0, 22.5, 45, -22.5, -45</code>。</td>
</tr>
<tr>
  <th>元素的面</th>
  <td><code>elements.face</code></td>
  <td>为方块的6个面纹理信息，东南西北上下6个面由xyz轴的方向确定，例如+x轴的面为东。</td>
</tr>
<tr>
  <th>元素纹理引用</th>
  <td><code>elements.face.[方向].texture</code></td>
  <td>指定所使用的纹理。建议绘制纹理时按照元素的南面展开图来排列各个面的纹理，即 <img src="items/南面展开图.png" alt="南面展开图" /> 或分为6个单独的纹理。可以为纹理的引用路径或以#开头的变量，使用变量的好处是便于修改。</td>
</tr>
<tr>
  <th>元素纹理范围</th>
  <td><code>elements.face.[方向].uv</code></td>
  <td>指定纹理的选取范围。将纹理放缩为16×16大小，该数值指定的便是相应区域。例如纹理文件为64×64大小，则 <code>"uv": [ 3.5, 3, 4, 4 ]</code> 使用的是距左上角横向14-16、纵向12-16的2×4个像素。</td>
</tr>
<tr>
  <th>纹理</th>
  <td><code>textures</code></td>
  <td>指定元素纹理引用中的变量所指的纹理文件位置。可以缺省并在子模型中指定以确定最终模型。</td>
</tr>
<tr>
  <th>颗粒纹理</th>
  <td><code>textures.particle</code></td>
  <td>指定作为物品或方块模型时，物品被损耗或方块被挖掘时显示的颗粒纹理。</td>
</tr>
</tbody></table>
<p class="noindent">更详细的语法参考<a href="https://zh.minecraft.wiki/w/模型">模型 - Minecraft Wiki，最详细的官方我的世界百科</a>。</p>
<figure>
  <img src="items/方向示意图.png" alt="方向示意图" />
  <figcaption>图3.1 方向示意图</figcaption>
</figure>

<p>如果我们循着模型 <code>minecraft:item/handheld</code> 往上，最终会得到模型 <code>builtin/generated</code>。这种模型是内建的，不能通过资源包来修改。</p>

<p>由于 <code>scale</code> 至多为4，而 <code>from to</code> 至多为<code>-16</code>到<code>32</code>，因此模型最多可以放大至<code>12</code>倍。想要更大的模型可以通过分段来旋转拼接而成，参阅</p>
<ul>
  <li><a href="https://www.mcbbs.net/thread-637959-1-1.html">因为不知道发到哪里只好发过来了 也不知道火没火星 毕竟我没有画纹理的朋友。。。</a></li>
  <li><a href="https://www.bilibili.com/video/av24626290">四十米长的大刀？我在minecraft里做1200米的！</a></li>
  <li><a href="https://www.bilibili.com/video/av39646162">【魔改纹理包】数体积专用-3轴标尺</a></li>
</ul>

<p>模型在不同位置仅有放缩旋转平移的差别，想要实现视觉上的明显不同，可参阅<a href="https://www.mcbbs.net/thread-833056-1-1.html">【1.14】物品头部/背包/手持显示不同纹理/模型</a>。</p>

<p>方块状态我们一般不会用到，而且语法比较简单，可直接参阅 wiki，这里不做赘述。</p>

<h2 id="纹理">§3.6 纹理</h2>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/textures/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/资源包#纹理" class="wiki">纹理</a></li>
  <li><a href="https://minecraft.wiki/w/Resource_Pack#Textures" class="wikien">Textures</a></li>
</ul>
<p>纹理 (Texture) 的绘制需要用到诸如 Photoshop 之类的画图软件，具体请参考纹理版或网络上的相关教程。</p>
<p>当模型调用的纹理不存在时，会显示紫黑色的纹理。如果模型是正确的，你仍然可以看出正确的模型形状。</p>
<p>纹理可以是动态的。动态纹理需要高为宽的整数倍，除非指定了 <code>width</code> 和 <code>height</code>。当纹理的高度为宽度的 <code>x</code> 倍时，可以有 <code>x</code> 帧，分别对应纹理自上而下均匀划分的 <code>x</code> 个块，从 <code>0</code> 开始。还需要一个 <code>mcmeta</code> 文件确定动画，例如 <code>foo.png</code> 对应</p>
<pre class="file" id="foo.png.mcmeta">foo.png.mcmeta</pre>
<pre>
{
  "animation": {
    "interpolate": true 或 false, <span class="comment">可选，是否需要插值过渡，默认为 false</span>
    "frametime": 正整数, <span class="comment">每一帧的默认时长，单位刻</span>
    "width": 数值, <span class="comment">每一帧的宽度，在帧不是正方形时需要该项来指定宽度</span>
    "height": 数值, <span class="comment">每一帧的高度，在帧不是正方形时需要该项来指定高度</span>
    "frames": [ <span class="comment">指定播放帧的次序</span>
      0, <span class="comment">帧的序号</span>
      1,
      4,
      3,
      {"index":2,"time": 2}, <span class="comment">单独指定这一帧的序号和时长，单位刻</span>
      3
    ]
  }
}
</pre>

<h2 id="音效">§3.7 音效</h2>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>音效文件路径</th><td><code><i>命名空间</i>/sounds/<i>路径</i>/<i>文件名</i>.ogg</code></td></tr>
  <tr><th>sounds.json</th><td><code><i>命名空间</i>/sounds.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/资源包#音效" class="wiki">音效</a></li>
  <li><a href="https://minecraft.wiki/w/Resource_Pack#Sounds" class="wikien">Sounds</a></li>
  <li><a href="https://zh.minecraft.wiki/w/Sounds.json" class="wiki">sounds.json</a></li>
  <li><a href="https://minecraft.wiki/w/Sounds.json" class="wikien">sounds.json</a></li>
</ul>
<p>音效 (Sound) 文件为 <code>assets/<i>命名空间</i>/sounds</code> 文件夹下的 <code>ogg</code> 文件，它需要JSON文件 <code>assets/<i>命名空间</i>/sounds.json</code> 来调用。音效文件会覆盖之前资源包的同名文件，但 <code>sounds.json</code> 默认会追加到上一个资源包中的相应内容。原版的音效文件和 <code>sounds.json</code> 并不位于<a href="#游戏本体">游戏本体</a>资源包，而是位于<a href="#资源文件">资源文件夹</a>下。</p>
<pre class="file" id="音效JSON格式">音效JSON格式</pre>
<pre>
{
  "声音事件名": { <span class="comment">声音事件名通常是按照类别以点(.)分割的</span>
    "replace": true 或 false (默认值), <span class="comment">替换还是追加之间的资源包中 sounds.json 的定义</span>
    "subtitle": "字符串", <span class="comment">可选，当游戏中开启了“显示字幕”时会在该声音事件被播放时将该字符串通过语言文件翻译为声音字幕</span>
    "sounds": [ <span class="comment">此声音事件触发时会随机选择列表中一个音效来播放</span>
      "音效文件命名空间ID"
    或
      {
        "type": "sound" (默认值) 或 "event", <span class="comment">可选，指定 name 的含义</span>
        "name": "音效文件命名空间ID" 或 "声音事件名", <span class="comment">type 为 sound 时为音效文件命名空间ID，type 为 event 时为声音事件名</span>
        "volume": 0~1 之间的数值, <span class="comment">可选，默认为1，该音效的音量</span>
        "pitch": 数值, <span class="comment">可选，默认为1，该音效的音调</span>
        "weight": 数值, <span class="comment">可选，默认为1，该音效被选中的权重</span>
        "stream": true 或 false (默认值), <span class="comment">可选，是否以流式播放，当声音较长时设为true可避免卡顿，例如原版音乐和唱片</span>
        "attenuation_distance": 数值, <span class="comment">可选，默认为16，基于距离的音效大小衰减率，用于传送门、信标和潮涌核心</span>
        "preload": true 或 false (默认值), <span class="comment">可选，是否在加载资源包时就加载该音效，而不是在播放音效的时候再加载，水下环境音效为 true</span>
      }
    ]
  }
}

</pre>

<p>例：</p>
<pre class="file" id="assets/rf/sounds">assets/rf/sounds.json</pre>
<pre>
{
  "item.rf.juicer": {
    "subtitle": "item.rf.juicer",
    "sounds": [
      "rf:juicer"
    ]
  },
  "item.rf.swing": {
    "sounds": [
      "rf:lightsaber/swing1",
      "rf:lightsaber/swing2",
      "rf:lightsaber/swing3",
      "rf:lightsaber/swing4"
    ]
  }
}
</pre>
<pre class="file" id="assets/rf/lang/zh_cn">assets/rf/lang/zh_cn.json</pre>
<pre>
{
  "item.rf.juicer": "饮用果汁",
  "item.rf.swing": "挥出光剑"
}
</pre>

<h2 id="字体">§3.8 字体 </h2>
<table><tbody>
  <tr><th>命名空间ID</th><td><code><i>命名空间</i>:<i>路径</i>/<i>文件名</i></code></td></tr>
  <tr><th>文件路径</th><td><code><i>命名空间</i>/font/<i>路径</i>/<i>文件名</i>.json</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/资源包#字体" class="wiki">字体</a></li>
  <li><a href="https://minecraft.wiki/w/Resource_Pack#Fonts" class="wikien">Fonts</a></li>
  <li><a href="https://www.mcbbs.net/thread-835539-1-1.html">【1.13】如何添加图片?</a></li>
  <li><a href="https://www.bilibili.com/video/av67508247">字体黑科技 —— 潜影盒内容预览</a></li>
</ul>
<p>字体 (Font) 提供了每个字符对应的资源位置和额外信息，其中 <code>minecraft:default</code> 给出了默认字体的样式，而 <code>minecraft:alt</code> 给出了附魔台所用的默认字体。在<a href="#原始JSON文本格式">原始JSON文本</a>中，若未指定字体则为 <code>minecraft:default</code> 的字体样式。</p>

<pre class="file" id="字体JSON格式">字体JSON格式</pre>
<pre>
{
  "providers": [
    {
      "type": "bitmap", <span class="comment">可以为 bitmap (位图)，legacy_unicode (旧版Unicode字体)，ttf (TrueType字体)，我们只考虑第一种</span>
      "file": "minecraft:font/mana0.png", <span class="comment">这些字符的资源位置，需要包含文件扩展名</span>
      "chars": [ <span class="comment">一个字符串列表，列表所有元素的字符数必须相同</span>
        "\ue010" <span class="comment">每一项元素对应纹理等距分割的一行，每一项元素中的字符对应等距的一列</span>
      ],
      "height": 91, <span class="comment">可选，该字符的显示的像素高度，可以为负</span>
      "ascent": 85 <span class="comment">该字符向上移动的像素高度，这个值会使得字符的显示结果出现垂直偏移</span>
    }
  ]
}
</pre>
<p>如果 <code>type</code> 为 <code>space</code>，则表示该字符表示空格，此时格式为</p>
<pre>
  {
    "providers": [
      {
        "type": "space",
        "advances": {
          "\ue010": 91, <span class="comment">
          该字符表示的空白长度</span>
          "\ue011": -10
      }
    ]
  }
</pre>
<p>我们来看一个例子。</p>
<pre class="file" id="assets/custom/font/default">assets/custom/font/default.json</pre>
<pre>
{
  "providers": [
    {
      "type": "space",
      "advances": {
        " ": 4,
        "A": -1024,
        "\uF81A": -190
      }
    },
    {
      "type": "bitmap",
      "file": "custom:font/mana0.png",
      "height": 91,
      "ascent": 85,
      "chars": ["\ue010"]
    },
    {
      "type": "bitmap",
      "file": "custom:font/mana1.png",
      "height": 91,
      "ascent": 85,
      "chars": ["\ue011"]
    }
  ]
}
</pre>
<pre class="file">命令</pre>
<pre>
tellraw @s {"text": "\ue010\ue011", "font": "custom:default"}
</pre>

<p>我们可以用 <code>\u</code> 开头来表示不容易打出的字符，参考<a href="https://unicode-table.com">Unicode® Character Table</a>，这与直接使用相应字符是等价的。</p>

<p>对于单纯的空格，我们需要使用 <code>space</code> 字形提供器。</p>

<p>利用这种方式，我们可以做到在成书、玩家快捷栏上方、聊天区域、物品名称等地方显示图片。利用负长度空格和垂直偏移，我们可以将图片显示在屏幕的任一位置。</p>
<p>例：我们在自定义字体中将0~9和:的纹理放大了一倍，并将其移动到左上角，使得其显示比通常位置高。然后利用负宽度空格将字符位置重新定位到快捷栏左侧，显示第二行文字。</p>
<pre class="file" id="assets/cpp/font/default">assets/cpp/font/default.json</pre>
<pre>{
  "providers": [
    {
      "type": "space",
      "advances": {
        " ": 4,
        "A": -1024,
        "\uF81A": -190
      }
    },
    {
      "type": "bitmap",
      "file": "cpp:font/immunized_from_poison.png",
      "height": 18,
      "ascent": 18,
      "chars": ["C"]
    },
    {
      "type": "bitmap",
      "file": "cpp:font/immunized_from_blindness.png",
      "height": 18,
      "ascent": 18,
      "chars": ["D"]
    },
    {
      "type": "bitmap",
      "file": "cpp:font/immunized_from_mining_fatigue.png",
      "height": 18,
      "ascent": 18,
      "chars": ["E"]
    },
    {
      "type": "bitmap",
      "file": "cpp:font/ascii1.png",
      "height": 18,
      "ascent": 18,
      "chars": ["\uF910\uF911\uF912\uF913\uF914\uF915\uF916\uF917\uF918\uF919\uF91A\uF91B\uF91C\uF91D\uF91E\uF91F"]
    },
    {
      "type": "bitmap",
      "file": "cpp:font/immunized_from_wither.png",
      "height": 8,
      "ascent": 8,
      "chars": ["F"]
    },
    {
      "type": "bitmap",
      "file": "cpp:font/immunized_from_darkness.png",
      "height": 8,
      "ascent": 8,
      "chars": ["G"]
    },
    {
      "type": "bitmap",
      "file": "cpp:font/weight_index.png",
      "height": 8,
      "ascent": 8,
      "chars": ["H"]
    },
    {
      "type": "bitmap",
      "file": "cpp:font/chain.png",
      "height": 8,
      "ascent": 8,
      "chars": ["I"]
    },
    {
      "type": "bitmap",
      "file": "cpp:font/immunized_from_mutation.png",
      "height": 8,
      "ascent": 8,
      "chars": ["J"]
    },
    {
      "type": "bitmap",
      "file": "cpp:font/sculking.png",
      "height": 8,
      "ascent": 8,
      "chars": ["K"]
    }
  ]
}
</pre>
<pre class="file">cpp:misc/fatness</pre>
<pre>
data remove storage cpp:_ title
setblock ~ 255 ~ oak_sign
scoreboard players operation #t cppValue = @s cppVacPoi
scoreboard players operation #t cppValue /= #3600 cppValue
function cpp:misc/number_to_ascii
scoreboard players operation #t cppValue = @s cppVacPoi
scoreboard players operation #t cppValue /= #600 cppValue
scoreboard players operation #t cppValue %= #6 cppValue
function cpp:misc/number_to_ascii
scoreboard players operation #t cppValue = @s cppVacPoi
scoreboard players operation #t cppValue /= #60 cppValue
scoreboard players operation #t cppValue %= #10 cppValue
function cpp:misc/number_to_ascii
scoreboard players operation #t cppValue = @s cppVacPoi
scoreboard players operation #t cppValue /= #10 cppValue
scoreboard players operation #t cppValue %= #6 cppValue
function cpp:misc/number_to_ascii
scoreboard players operation #t cppValue = @s cppVacPoi
scoreboard players operation #t cppValue %= #10 cppValue
function cpp:misc/number_to_ascii

scoreboard players operation #t cppValue = @s cppVacBli
scoreboard players operation #t cppValue /= #3600 cppValue
function cpp:misc/number_to_ascii
scoreboard players operation #t cppValue = @s cppVacBli
scoreboard players operation #t cppValue /= #600 cppValue
scoreboard players operation #t cppValue %= #6 cppValue
function cpp:misc/number_to_ascii
scoreboard players operation #t cppValue = @s cppVacBli
scoreboard players operation #t cppValue /= #60 cppValue
scoreboard players operation #t cppValue %= #10 cppValue
function cpp:misc/number_to_ascii
scoreboard players operation #t cppValue = @s cppVacBli
scoreboard players operation #t cppValue /= #10 cppValue
scoreboard players operation #t cppValue %= #6 cppValue
function cpp:misc/number_to_ascii
scoreboard players operation #t cppValue = @s cppVacBli
scoreboard players operation #t cppValue %= #10 cppValue
function cpp:misc/number_to_ascii

scoreboard players operation #t cppValue = @s cppVacMin
scoreboard players operation #t cppValue /= #3600 cppValue
function cpp:misc/number_to_ascii
scoreboard players operation #t cppValue = @s cppVacMin
scoreboard players operation #t cppValue /= #600 cppValue
scoreboard players operation #t cppValue %= #6 cppValue
function cpp:misc/number_to_ascii
scoreboard players operation #t cppValue = @s cppVacMin
scoreboard players operation #t cppValue /= #60 cppValue
scoreboard players operation #t cppValue %= #10 cppValue
function cpp:misc/number_to_ascii
scoreboard players operation #t cppValue = @s cppVacMin
scoreboard players operation #t cppValue /= #10 cppValue
scoreboard players operation #t cppValue %= #6 cppValue
function cpp:misc/number_to_ascii
scoreboard players operation #t cppValue = @s cppVacMin
scoreboard players operation #t cppValue %= #10 cppValue
function cpp:misc/number_to_ascii

scoreboard players operation #t1 cppValue = @s cppVacWit
scoreboard players operation #t1 cppValue /= #3600 cppValue
scoreboard players operation #t2 cppValue = @s cppVacWit
scoreboard players operation #t2 cppValue /= #600 cppValue
scoreboard players operation #t2 cppValue %= #6 cppValue
scoreboard players operation #t3 cppValue = @s cppVacWit
scoreboard players operation #t3 cppValue /= #60 cppValue
scoreboard players operation #t3 cppValue %= #10 cppValue
scoreboard players operation #t4 cppValue = @s cppVacWit
scoreboard players operation #t4 cppValue /= #10 cppValue
scoreboard players operation #t4 cppValue %= #6 cppValue
scoreboard players operation #t5 cppValue = @s cppVacWit
scoreboard players operation #t5 cppValue %= #10 cppValue
data modify block ~ 255 ~ Text1 set value '[{"score":{"name":"#t1","objective":"cppValue"}},":",{"score":{"name":"#t2","objective":"cppValue"}},{"score":{"name":"#t3","objective":"cppValue"}},":",{"score":{"name":"#t4","objective":"cppValue"}},{"score":{"name":"#t5","objective":"cppValue"}}]'

scoreboard players operation #t1 cppValue = @s cppVacDar
scoreboard players operation #t1 cppValue /= #3600 cppValue
scoreboard players operation #t2 cppValue = @s cppVacDar
scoreboard players operation #t2 cppValue /= #600 cppValue
scoreboard players operation #t2 cppValue %= #6 cppValue
scoreboard players operation #t3 cppValue = @s cppVacDar
scoreboard players operation #t3 cppValue /= #60 cppValue
scoreboard players operation #t3 cppValue %= #10 cppValue
scoreboard players operation #t4 cppValue = @s cppVacDar
scoreboard players operation #t4 cppValue /= #10 cppValue
scoreboard players operation #t4 cppValue %= #6 cppValue
scoreboard players operation #t5 cppValue = @s cppVacDar
scoreboard players operation #t5 cppValue %= #10 cppValue
data modify block ~ 255 ~ Text2 set value '[{"score":{"name":"#t1","objective":"cppValue"}},":",{"score":{"name":"#t2","objective":"cppValue"}},{"score":{"name":"#t3","objective":"cppValue"}},":",{"score":{"name":"#t4","objective":"cppValue"}},{"score":{"name":"#t5","objective":"cppValue"}}]'

scoreboard players operation #t1 cppValue = @s cppVacMut
scoreboard players operation #t1 cppValue /= #3600 cppValue
scoreboard players operation #t2 cppValue = @s cppVacMut
scoreboard players operation #t2 cppValue /= #600 cppValue
scoreboard players operation #t2 cppValue %= #6 cppValue
scoreboard players operation #t3 cppValue = @s cppVacMut
scoreboard players operation #t3 cppValue /= #60 cppValue
scoreboard players operation #t3 cppValue %= #10 cppValue
scoreboard players operation #t4 cppValue = @s cppVacMut
scoreboard players operation #t4 cppValue /= #10 cppValue
scoreboard players operation #t4 cppValue %= #6 cppValue
scoreboard players operation #t5 cppValue = @s cppVacMut
scoreboard players operation #t5 cppValue %= #10 cppValue
data modify block ~ 255 ~ Text3 set value '[{"score":{"name":"#t1","objective":"cppValue"}},":",{"score":{"name":"#t2","objective":"cppValue"}},{"score":{"name":"#t3","objective":"cppValue"}},":",{"score":{"name":"#t4","objective":"cppValue"}},{"score":{"name":"#t5","objective":"cppValue"}}]'

execute as @s[scores={cppFat=..-100}] run data modify storage cpp:_ title append value '{"translate":"title.actionbar.fat0"}'
execute as @s[scores={cppFat=-99..-50}] run data modify storage cpp:_ title append value '{"translate":"title.actionbar.fat1"}'
execute as @s[scores={cppFat=-49..49}] run data modify storage cpp:_ title append value '{"translate":"title.actionbar.fat2"}'
execute as @s[scores={cppFat=50..100}] run data modify storage cpp:_ title append value '{"translate":"title.actionbar.fat3"}'
execute as @s[scores={cppFat=100..}] run data modify storage cpp:_ title append value '{"translate":"title.actionbar.fat4"}'

title @s actionbar [{"text":"C ","font":"cpp:default"},{"storage":"cpp:_","nbt":"title[0]","interpret":true},"\uF91A",{"storage":"cpp:_","nbt":"title[1]","interpret":true},{"storage":"cpp:_","nbt":"title[2]","interpret":true},"\uF91A",{"storage":"cpp:_","nbt":"title[3]","interpret":true},{"storage":"cpp:_","nbt":"title[4]","interpret":true},"    D ",{"storage":"cpp:_","nbt":"title[5]","interpret":true},"\uF91A",{"storage":"cpp:_","nbt":"title[6]","interpret":true},{"storage":"cpp:_","nbt":"title[7]","interpret":true},"\uF91A",{"storage":"cpp:_","nbt":"title[8]","interpret":true},{"storage":"cpp:_","nbt":"title[9]","interpret":true},"    E ",{"storage":"cpp:_","nbt":"title[10]","interpret":true},"\uF91A",{"storage":"cpp:_","nbt":"title[11]","interpret":true},{"storage":"cpp:_","nbt":"title[12]","interpret":true},"\uF91A",{"storage":"cpp:_","nbt":"title[13]","interpret":true},{"storage":"cpp:_","nbt":"title[14]","interpret":true},"    \uF81AF ",{"block":"~ 255 ~","nbt":"Text1","interpret":true,"font":"default"},{"text":"    G ","font":"cpp:default"},{"block":"~ 255 ~","nbt":"Text2","interpret":true,"font":"default"},{"text":"    J ","font":"cpp:default"},{"block":"~ 255 ~","nbt":"Text3","interpret":true,"font":"default"},{"text":"    H ","font":"cpp:default"},{"score":{"name":"@s","objective":"cppFat"},"font":"default"},{"storage":"cpp:_","nbt":"title[15]","interpret":true,"font":"default"}]
setblock ~ 255 ~ air
</pre>
<pre class="file" id="cpp/functions/misc/number_to_ascii">cpp:misc/number_to_ascii</pre>
<pre>
execute if score #t cppValue matches 0 run data modify storage cpp:_ title append value '{"text":"\\uF910","font":"cpp:default"}'
execute if score #t cppValue matches 1 run data modify storage cpp:_ title append value '{"text":"\\uF911","font":"cpp:default"}'
execute if score #t cppValue matches 2 run data modify storage cpp:_ title append value '{"text":"\\uF912","font":"cpp:default"}'
execute if score #t cppValue matches 3 run data modify storage cpp:_ title append value '{"text":"\\uF913","font":"cpp:default"}'
execute if score #t cppValue matches 4 run data modify storage cpp:_ title append value '{"text":"\\uF914","font":"cpp:default"}'
execute if score #t cppValue matches 5 run data modify storage cpp:_ title append value '{"text":"\\uF915","font":"cpp:default"}'
execute if score #t cppValue matches 6 run data modify storage cpp:_ title append value '{"text":"\\uF916","font":"cpp:default"}'
execute if score #t cppValue matches 7 run data modify storage cpp:_ title append value '{"text":"\\uF917","font":"cpp:default"}'
execute if score #t cppValue matches 8 run data modify storage cpp:_ title append value '{"text":"\\uF918","font":"cpp:default"}'
execute if score #t cppValue matches 9 run data modify storage cpp:_ title append value '{"text":"\\uF919","font":"cpp:default"}'
</pre>

<h2 id="着色器">§3.9 着色器</h2>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/资源包#着色器" class="wiki">着色器</a></li>
  <li><a href="https://minecraft.wiki/w/Shaders" class="wikien">Shaders</a></li>
  <li><a href="https://www.mcbbs.net/thread-916150-1-1.html">原版着色器指导</a></li>
  <li><a href="https://www.mcbbs.net/thread-917679-1-1.html">几个原版着色器示例</a></li>
  <li><a href="https://www.mcbbs.net/thread-863730-1-1.html">原版资源包着色器与动画研究心得</a></li>
  <li><a href="https://www.mcbbs.net/thread-1056196-1-1.html">不会有人看的深度缓冲着色器分析&用途</a></li>
  <li><a href="https://www.mcbbs.net/thread-1181123-1-1.html">核心着色器浅析</a></li>
</ul>
<p>着色器 (Shader) 用于描绘如何渲染游戏，包含后处理着色器和核心着色器。</p>

<h3 id="后处理着色器">§3.9.1 后处理着色器</h3>
<table><tbody>
  <tr><th>后处理着色器渲染管线文件</th><td><code>minecraft/shaders/post/<i>文件名</i>.json</code></td></tr>
  <tr><th>着色器程序文件</th><td><code>minecraft/shaders/program/<i>文件名</i>.json</code></td></tr>
  <tr><th>顶点着色器文件</th><td><code>minecraft/shaders/program/<i>文件名</i>.vsh</code></td></tr>
  <tr><th>片段着色器文件</th><td><code>minecraft/shaders/program/<i>文件名</i>.fsh</code></td></tr>
</tbody></table>
<p>后处理着色器会在游戏已经渲染好画面以后再起效，它们能够接受整个屏幕的像素作为输入，然后逐像素地输出。除了一些有限的特例以外，着色器所能接受到的唯一数据就是正显示在屏幕上的内容。我们只能通过在资源包替换 <code>minecraft/shaders/post/<i>文件名</i>.json</code> 下的下述文件来修改：</p>
<ul>
  <li><code>creeper.json</code> 将在以苦力怕视角旁观时启用；</li>
  <li><code>invert.json</code> 将在以末影人视角旁观时启用；</li>
  <li><code>spider.json</code> 将在以蜘蛛视角旁观时启用；</li>
  <li><code>entity_outline.json</code> 将在屏幕中有具有发光状态效果的实体时启用；</li>
  <li><code>transparency.json</code> 将在玩家启用了“极佳”图像品质时启用。</li>
</ul>

<p>在后处理着色器渲染管线中，除了玩家自定义的缓冲层，系统还预设了</p>
<ul>
  <li>为发光着色器准备的、预先填充好的特殊缓冲层：<code>minecraft:main</code> (没有水、方块实体和其他一些东西) 和 <code>final</code> (纯色的实体，颜色是该实体所在队伍的颜色)；</li>
  <li>为实体视角着色器准备的、预先填充好的特殊缓冲层：<code>minecraft:main</code> (所有内容都已渲染完成)。</li>
</ul>
<p>当屏幕渲染完成时，若玩家处于上述5种情形，则会对调用相应的后处理着色器渲染管线文件来依次对缓冲层进行着色器程序操作，并最终返回到缓冲层 <code>minecraft:main</code>。</p>

<pre class="file" id="后处理着色器渲染管线JSON格式">后处理着色器渲染管线JSON格式</pre>
<pre>
{
  "targets": [ <span class="comment">缓冲层</span>
    "字符串" <span class="comment">使用默认窗口高度和宽度</span>
  或
    {
      "name": "字符串",
      "width": 整数, <span class="comment">宽度</span>
      "height": 整数 <span class="comment">高度</span>
    }
  ],
  "passes": [
    {
      "name": "prog1", <span class="comment">着色器程序</span>
      "intarget": "minecraft:main", <span class="comment">输入缓冲层</span>
      "outtarget": "foo" <span class="comment">输出缓冲层</span>
    },
    {
      "name": "prog2",
      "intarget": "foo",
      "auxtargets": [ <span class="comment">为着色器程序提供缓冲层或图片</span>
        {
          "name": "字符串", <span class="comment">该参数名，以便着色器程序能访问它</span>
          "id": "字符串", <span class="comment">由 targets 定义的缓冲区，或者 assets/<i>命名空间</i>/textures/effect 下的纹理(使用命名空间ID来引用)</span>
          "width": 整数, <span class="comment">如果引用的是纹理，该项必须，指纹理的宽度</span>
          "height": 整数, <span class="comment">如果引用的是纹理，该项必须，指纹理的高度</span>
          "bilinear": true 或 false <span class="comment">如果引用的是纹理，该项必须，指纹理的缩放算法为双线性还是邻近</span>
        }
      ],
      "outtarget": "bar"
    },
    {
      "name": "blit", <span class="comment">blit 指仅复制缓冲层内容而不做任何修改</span>
      "uniforms": { <span class="comment">为着色器程序提供一个浮点数数组</span>
        {
          "name": "字符串", <span class="comment">将要传递的参数名</span>
          "values": 数值
      },
      "intarget": "bar",
      "outtarget": "minecraft:main"
    }
  ]
}
</pre>

<p>我们可以在 <code>minecraft/shaders/program</code> 文件夹下创建自定义名称的着色器程序文件。其中顶点着色器会对每个顶点起效，将顶点的位置作为输入，并产生一个经过变换的位置作为输出。片段着色器会对每个像素起效，并逐像素产生输出层。</p>
<pre class="file" id="着色器程序JSON格式">着色器程序JSON格式</pre>
<pre>
{
  "blend": { <span class="comment">OpenGL混合设置，我们使用常用设置</span>
    "func": "add",
    "srcrgb": "one",
    "dstrgb": "zero"
  },
  "vertex": "foo", <span class="comment">将要使用的顶点着色器 .vsh 文件的文件名。</span>
  "fragment": "foo", <span class="comment">将要使用的片段着色器 .fsh 文件的文件名。</span>
  "attributes": [ "Position" ],
  "samplers": [ 
    { "name": "DiffuseSampler" }, <span class="comment">指由 intarget 给予的缓冲层的变量名</span>
    { "name": "DitherSampler" } <span class="comment">其它名称的需要由 auxtargets 给予</span>
  ],
  "uniforms": [ <span class="comment">全局变量，数据类型type为 float, vec2, vec3, vec4, int, ivec2, ivec3, ivec4, matrix4x4, matrix3x3 或 matrix2x2</span>
    { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
    { "name": "InSize",  "type": "float", "count": 2,  "values": [ 1.0, 1.0 ] },
    { "name": "OutSize", "type": "float", "count": 2,  "values": [ 1.0, 1.0 ] },
    { "name": "BlurDir", "type": "float", "count": 2,  "values": [ 1.0, 1.0 ] },
    { "name": "Radius",  "type": "float", "count": 1,  "values": [ 5.0 ] }
  ]
}
</pre>
<p>这里全局变量的 <code>count</code> 为 <code>values</code> 数组的长度，当为浮点数 (<code>float</code>) 时，实际为 <code>count</code> 长度的浮点数数组 <code>float, vec2, vec3, vec4</code>；<code>int</code> 类似，为 <code>int, ivec3, ivec3, ivec4</code>；矩阵为 <code>matrix4x4, matrix3x3, matrix2x2</code>。</p>

<p>顶点着色器和片段着色器程序可参考原版着色器的 <code>vsh, fsh</code> 文件。着色器中的数据类型包括标量 <code>bool, int, uint, float, double</code>，向量 <code>bven, iven, uven, ven, dven</code>，<code><i>n</i>=2,3,4</code> 为向量长度；矩阵 <code>mat<i>n</i>, mat<i>n</i>x<i>m</i></code> 为列优先的矩阵，<code><i>n,m</i>=2,3,4</code>。构建变量时，可以使用其它变量作为其部分。全局变量可以被声明为</p>
<ul>
  <li><code>in</code>，只能被顶点着色器读取，它自动包含了当前顶点的 Position（位置）属性；</li>
  <li><code>uniform</code>，可以被顶点着色器与片段着色器读取，对所有的顶点或像素都会保持恒定不变，它们的值可以通过后处理 JSON 文件传入，否则将会使用在着色器程序 JSON 文件中定义的默认值；</li>
  <li><code>out</code>，由顶点着色器声明并赋值，然后可在片段着色器中被读取，这些值会在顶点间插值计算出来。</li>
</ul>
<p>着色器程序中的 <code>main</code> 函数会在该着色器程序被调用时执行。更多关于着色器程序的内容请点击上方链接来阅读。</p>

<p>例：这个片段着色器会放大图像中心圆形区域图案。屏幕上左下角像素坐标为 <code>(0,0)</code>，右上角为 <code>(1,1)</code>。</p>
<pre>
#version 150

uniform sampler2D DiffuseSampler;

in vec2 texCoord;
in vec2 oneTexel;

out vec4 fragColor;

void main(){
  float distFromCenter = distance(texCoord, vec2(0.5, 0.5));
  if (distFromCenter &lt; 0.38) {
    vec2 zoomedCoord = ((texCoord - vec2(0.5, 0.5)) * 0.2) + vec2(0.5, 0.5);
    fragColor = texture(DiffuseSampler, zoomedCoord);
  } else if (distFromCenter >= 0.38 && distFromCenter &lt; 0.4) {
    fragColor = vec4(0.7, 0.4, 0.1, 1.0); 
  } else {
    fragColor = texture2D(DiffuseSampler, texCoord);
  }
}
</pre>

<h3 id="核心着色器">§3.9.2 核心着色器</h3>
<p>所有能在屏幕上看到的东西都是由核心着色器渲染的，核心着色器文件位于 <code>assets/minecraft/shaders/core</code> 文件夹下。游戏的每个部分会调用相应的核心着色器来渲染。如果我们不希望对着色器进行全局修改，我们可以通过纹理坐标检测在渲染什么，然后进行相应的着色器程序。然而，纹理的 atlas 依赖于加载的所有资源包，因此一旦添加了纹理，纹理坐标将会发生改变。更详细的内容请点击上方链接来阅读。</p>

<h2 id="文本">§3.10 文本</h2>

<table><tbody>
  <tr><th>制作人员名单</th><td><code>minecraft/texts/credits.json</code></td></tr>
  <tr><th>终末之诗</th><td><code>minecraft/texts/end.txt</code></td></tr>
  <tr><th>闪烁标语</th><td><code>minecraft/texts/splashes.txt</code></td></tr>
</tbody></table>
<ul class="link">
  <li><a href="https://zh.minecraft.wiki/w/资源包#文本" class="wiki">文本</a></li>
  <li><a href="https://minecraft.wiki/w/Resource_Pack#Texts" class="wikien">Texts</a></li>
</ul>

<p>玩家首次进入末地的主世界返回传送门时，会播放终末之诗和制作人员名单。文本PLAYERNAME将会被玩家名称代替。我们可以修改之以显示模组的一些内容。文件 <code>splashes.txt</code> 中每一行表示一个单独的闪烁标语，可以使用样式代码。</p>
<p>1.16以及更早版本可使用样式代码，以及使用 <code>[C]</code> 来表示居中，且这些版本制作人员名单是txt格式。</p>


<h1 id="规划">§4 规划</h1>
<p>当我们有了一定的命令基础和数据包与资源包的相关知识之后，我们可以开始考虑做一个模组了。模组的目的是在原版的基础上做出一定的修改，模组的核心是内容，命令和技巧都只是为实现这一目的的手段。通常的设计路线如下图所示：</p>
<figure>
  <img src="items/设计路线.png" alt="设计路线" />
  <figcaption>图4.1 设计路线</figcaption>
</figure>
<p class="noindent">平衡性可以从合成难度和触发条件等方面来调整。</p>

<p>原版模组不比基于 Forge/Liteloader 等 API 的模组，在实现效率上一般会有所欠缺，因此我们在制作和测试过程中，应当优先保证流畅度，再考虑内容的充实性。</p>
<p>模组的整个生命周期中，所有内容都应当有完整的文档记录，以便于随时查看和修改。</p>
<p>为你的模组设定合理的版本管理方式，例如使用 Git 托管，有利于保存模组的所有历史版本。这可以减少因误操作导致的损失。</p>

<h2 id="名称设计">§4.1 名称设计</h2>
<p>模组的所有内容都应当被合理地命名，尽量采用简洁且有意义的命名，同时便于他人处理数据包冲突。这些内容包括数据包下所有的文件和文件夹名以及记分板、标签、组的名称等。建议各种名称均使用大驼峰、小驼峰或下划线记法。如果模组包含多个模块，可以在不同数据包下使用相同的命名空间、不同的文件夹，来分门别类。</p>
<table><thead><tr><th style="width:7em;">类型</th><th>示例</th><th>说明</th></tr></thead><tbody>
<tr>
  <th>数据包名称</th>
  <td><code>craftingpp<br/>更多的合成v1.10<br/>CraftingPlusPlus</code></td>
  <td>建议使用模组全名，空格和特殊字符使用下划线代替或忽略，也可使用中文名称。</td>
</tr>
<tr>
  <th>资源包名称</th>
  <td><code>craftingpp_resourcepack<br/>更多的合成v1.10资源包<br/>CraftingPlusPlus_Resources</code></td>
  <td>建议使用数据包名称+资源包等。</td>
</tr>
<tr>
  <th>命名空间</th>
  <td><code>craftingpp<br/>ex<br/>fisma<br/>mek</code></td>
  <td>过短的命名空间容易冲突，可使用模组名称的全程或缩写来表示。命名空间必须由小写或下划线组成。建议整个模组使用一个命名空间，或若干相同前缀的命名空间。</td>
</tr>
<tr>
  <th>物品名称</th>
  <td><code>红色火之力<br/>Red Force of Fire<br/>cpp:red_force_of_fire</code></td>
  <td>建议使用物品英文名称对应的小写+下划线写法作为物品id，具体设计见下一节。</td>
</tr>
<tr>
  <th>记分板和组</th>
  <td><code>cppValue<br/>exCraft<br/>macTicks<br/>cpp_health</code></td>
  <td>建议使用命名空间为前缀的驼峰记法，因为记分板名称长度不可超过16。长度允许的话，使用下划线记法也可以。</td>
</tr>
<tr>
  <th>实体标签</th>
  <td><code>cpp_entities_checker<br/>cpp_generate_dead<br/>cpp_machines_marker<br/>exDarkAnimals</code></td>
  <td>建议使用命名空间为前缀。</td>
</tr>
<tr>
  <th>自定义NBT键</th>
  <td><code>exGenratorMarker<br/>exLeavesDecayMarker<br/>exSkyislandDrop</code></td>
  <td>建议使用命名空间为前缀。</td>
</tr>
<tr>
  <th>记分板假名</th>
  <td><code>#temp<br/>$machineWorkPeriod<br/>$mod_leaves_speed</code></td>
  <td>临时变量建议使用#开头，配置参数建议使用$开头，因为#开头的计分板不会在记分板列表中显示而$开头的可以。因记分板已使用前缀，此处可以不使用前缀。</td>
</tr>
<tr>
  <th>tick函数</th>
  <td><code>_main.mcfunction<br/>tick.mcfunction<br/>loop.mcfunction</code></td>
  <td>即函数标签 <code>minecraft:tick</code> 下的函数，见 <a href="#预设标签">§2.10.1 预设标签</a>。</td>
</tr>
<tr>
  <th>load函数</th>
  <td><code>load.mcfunction<br/>_init.mcfunction<br/>root.mcfunction</code></td>
  <td>即函数标签 <code>minecraft:load</code> 下的函数，见 <a href="#预设标签">§2.10.1 预设标签</a>。</td>
</tr>
</tbody></table>

<h2 id="调试">§4.2 调试</h2>
<p>加载中出现的资源包和数据包错误一般会在 <code>logs/latest.log</code> 中提示，见 <a href="#游戏文件结构">§1.3.1 游戏文件结构</a>。测试时，打开这个文件，可以看到具体是哪个文件的哪个位置发生了错误。常见错误包括</p>

<table><thead><tr><th>日志</th><th>说明</th></tr></thead><tbody>
<tr>
  <td><code>Unable to load model: '模型引用名' referenced from: 某物品#inventory: java.lang.IllegalStateException: Not aJSONObject: "parent"</code></td>
  <td>该物品模型文件中调用的另一模型出错，错误出在 <code>"parent"</code></td>
</tr>
<tr>
  <td><code>Using missing texture, unable to load</code></td>
  <td>相应路径的纹理不存在。</td>
</tr>
<tr>
  <td><code>Couldn't load function at 函数路径 java.util.concurrent.CompletionException: java.lang.IllegalArgumentException: Whilst parsing command on line 行号 at position 列号</code></td>
  <td>相应函数的相应位置出错。</td>
</tr>
<tr>
  <td><code>Couldn't read function tag list 标签引用名 from 标签路径 in data pack 数据包</code></td>
  <td>相应数据包的相应路径的标签出错，检查下是否调用了不存在的物品、方块或出错的函数，或是逗号使用错误。</td>
</tr>
</tbody></table>
<p class="noindent">使用 <code>/datapack list</code> 来查看你的模组是否被识别了，如果压根没识别说明你的模组缺少 <code>pack.mcmeta</code> 或其错误。</p>
<p>如果进游戏异常卡顿，输入 <code>/function 相应高频函数</code>，如果提示执行了65535条函数，那么可能是函数使用了无限自我递归调用。检查相应的函数递归是否跳出条件有误。</p>
<p>调试时，可添加适当的 <code>tellraw</code> 命令来查看方块、实体、记分板值等，来确定何处出错。</p>

<h2 id="前置与附属">§4.3 前置与附属</h2>
<p>使用他人已写好的前置可以在减少自己的工作量，例如</p>
<ul>
  <li><a href="https://www.mcbbs.net/thread-900914-1-1.html">战利品表随机数</a></li>
  <li><a href="https://www.mcbbs.net/thread-916294-1-1.html">方块通用处理</a></li>
  <li><a href="https://github.com/ruhuasiyu/CraftingPlusPlus/tree/master/other_datapacks/%E5%90%88%E6%88%90%E9%80%9A%E7%94%A8%E5%A4%84%E7%90%86">合成通用处理</a></li>
  <li><a href="https://github.com/ruhuasiyu/CraftingPlusPlus/tree/master/other_datapacks/%E5%8E%9F%E7%89%88%E6%A8%A1%E7%BB%84%E5%AE%B9%E5%99%A8%E6%89%A9%E5%B1%95">原版模组容器扩展</a></li>
  <li><a href="https://www.mcbbs.net/thread-775667-1-1.html">【UIN】数据包——标签分类</a></li>
</ul>
<p class="noindent">等。这些前置已经包含了诸如生成随机数、处理模组方块、合成、容器等内容，这样开发者就不用再花费精力在这些事件的处理上，只需要调用它们提供的接口即可。使用这些数据包之前，应当对其内容有充分的了解再考虑引用，他人的代码未必是合理高效无漏洞的。</p>

<p>建议在前置中添加函数</p>
<pre class="file" id="foo:datapack">foo:datapack</pre>
<pre>
scoreboard players set #datapack_version fooValue 101
</pre>
<p class="noindent">这样他人便可通过在<code>load函数</code>中添加
<pre class="file" id="bar:load">bar:load</pre>
<pre>
scoreboard objective add fooValue dummy
scoreboard players set #datapack_version fooValue 0
function foo:datapack
execute unless score #datapack_version fooValue matches 101 run tellraw @a {"text":"[Bar模组]：缺少必要的数据包前置[Foo模组v1.0.1]！"}
</pre>
<p class="noindent">以在缺少相应版本的前置时提醒使用者。</p>

<p>附属一般通过函数标签来实现。例如在你的模组中添加了一种机器，里面对物品进行了一些处理：</p>
<pre class="file" id="foo:machine/tick">foo:machine/tick</pre>
<pre>
execute if block ~ ~ ~ barrel{Items:[{Slot:3b,id:"minecraft:mycelium"},{Slot:12b,id:"minecraft:dirt"}]} run item block ~ ~ ~ container.15 replace minecraft:mycelium
function #foo:item_processer
</pre>
<p class="noindent">那么其它开发者就可以通过在函数标签 <code>#foo:item_processer</code> 中添加相应的函数命令来实现更多的机器配方。</p>

<h2 id="发布">§4.4 发布</h2>
<p>当你设计并制作好全部内容且通过测试后，将你的数据包以及其它可能的内容，如资源包、地图、data文件等一同发布。采用合适的版本号管理，并在发布时注明你所使用的命名空间、记分板、组、标签、地图区段、资源包等内容，以便于其他开发者整合或避免冲突。</p>
<p>如果你认为分别发布数据包和资源包两个压缩文件不够方便的话，你可以将二者内容放在同一个文件夹下压缩，使得二者共用 <code>pack.mcmeta</code> 和 <code>pack.png</code>。使用时，只需将其分别复制一份到数据包和资源包文件夹使用即可。</p>
<p>如果你的模组内容较多，可以建立一个wiki页面来方便玩家查询资料。例如国内最大的中文 Minecraft 模组百科<a href="https://www.mcmod.cn/">MC 百科</a>，建立模组后，可以申请编辑员来方便地管理你的模组wiki页面。也可以 Github 的项目中创建 wiki。</p>


<h1 id="物品设计">§5 物品设计</h1>
<h2 id="通用处理">§5.1 通用处理</h2>
<p>由于原版模组从不添加原版不存在的物品，所以我们需要为物品加上NBT来进行区分。我们以一例来看模组物品通常包含哪些NBT。</p>
<p class="ex"> 添加物品红色火之力，不可叠加，右键触发执行命令。我们可使用胡萝卜钓竿/诡异疣钓竿作为物品本体，这里我们以胡萝卜钓竿为例。我们建议为模组添加的所有物品添加相应的战利品表来便于获取/修改/合成等。</p>

<pre class="file" id="cpp/loot_tables/red_force_of_fire">cpp/loot_tables/red_force_of_fire.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "item",
          "name": "minecraft:carrot_on_a_stick",
          "functions": [
            {
              "function": "set_name",
              "name": {
                "color": "#FF0000",
                "translate": "item.ex.red_force_of_fire"
              }
            },
            {
              "function": "set_nbt",
              "tag": "{id:'cpp:red_force_of_fire',CustomModelData:12970013}"
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<table><thead><tr><th>NBT</th><th>说明</th></tr></thead><tbody>
<tr>
  <td><code>id:"cpp:red_force_of_fire"</code></td>
  <td>建议使用<code>id:"命名空间:物品名称"</code>来表示原版模组物品的唯一标签，以与其它模组的物品区分。</td>
</tr>
<tr>
  <td><code>display:{Name:'{"translate":"item.ex.red_force_of_fire"}'}</code></td>
  <td>物品的显示名称，建议使用<code>translate</code>文本，以支持多种语言，见 <a href="#语言文件">§3.3 语言文件</a>。</td>
</tr>
<tr>
  <td><code>CustomModelData:12970013</code></td>
  <td>物品的自定义模型数据，见 <a href="#自定义物品模型">§3.4 自定义物品模型</a>。</td>
</tr>
<tr>
  <td><code>dict:["iron_dust"]</code></td>
  <td>可选的矿物辞典，用于表示同类物品，并不一定指矿物类物品。例如矿物、矿物粉、矿物粒、水果等。矿物辞典可用来解决不同的原版模组/插件的同种物品互相调用的问题，见<a href="https://www.mcmod.cn/post/927.html">原版模组矿物辞典</a>。</td>
</tr>
</tbody></table>

<p class="noindent">然后为物品添加模型，见 <a href="#模型">§3.5 模型</a>。</p>
<pre class="file">assets/minecraft/models/item/carrot_on_a_stick.json</pre>
<pre>
{
  "parent": "item/handheld_rod",
  "textures": {
    "layer0": "item/carrot_on_a_stick"
  },
  "overrides": [
    { "predicate": { "custom_model_data": 12970013 }, "model": "cpp:tools/red_force_of_fire"}
  ]
}
</pre>
<pre class="file" id="assets/cpp/models/tools/red_force_of_fire">assets/cpp/models/tools/red_force_of_fire.json</pre>
<pre>
{
  "parent": "item/handheld_rod",
  "textures": {
    "layer0": "cpp:tools/red_force_of_fire"
  }
}
</pre>
<p class="noindent">最后，为其绘制纹理 <code>assets/cpp/textures/tools/red_force_of_fire.png</code>。这样我们便将这个物品初步设计完成。</p>

<p>我们会在本节接下来的段落介绍不同功能物品的设计。对于方块形式，我们则会在后续章节中介绍。</p>

<h2 id="右键交互">§5.2 右键交互</h2>
<p>对于右键具有交互功能的物品，我们可以使用胡萝卜钓竿，通过使用胡萝卜钓竿的记分板来探测。例如使用上一节中的示例物品：</p>
<pre class="file">cpp:load</pre>
<pre>
scoreboard objectives add cppUseCSt minecraft.used:minecraft.carrot_on_a_stick
</pre>
<pre class="file">cpp:tick</pre>
<pre>
execute as @a[scores={cppUseCSt=1..}] run function <a href="#cpp/functions/use_cst">cpp:use_cst</a>
</pre>
<pre class="file" id="cpp/functions/use_cst">cpp:use_cst</pre>
<pre>
execute as @s[predicate=<a href="#cpp/predicates/hand/red_force_of_fire">cpp:hand/red_force_of_fire</a>] run function <a href="#cpp/functions/tools/red_force_of_fire">cpp:tools/red_force_of_fire</a>
scoreboard players reset @s cppUseCSt
</pre>
<pre class="file" id="cpp/predicates/hand/red_force_of_fire">cpp/predicates/hand/red_force_of_fire.json</pre>
<pre>
{
  "condition": "minecraft:alternative",
  "terms":[
    {
      "condition": "minecraft:entity_properties",
      "entity": "this",
      "predicate": {
        "equipment": {
          "mainhand":{
            "items": ["minecraft:carrot_on_a_stick"],
            "nbt": "{id:'cpp:red_force_of_fire'}"
          }
        }
      }
    },
    {
      "condition": "minecraft:inverted",
      "term": {
        "condition": "minecraft:alternative",
        "terms": [
          {
            "condition": "minecraft:entity_properties",
            "entity": "this",
            "predicate": {
              "equipment": {
                "mainhand":{
                  "items": ["minecraft:carrot_on_a_stick"]
                }
              }
            }
          },
          {
            "condition": "minecraft:inverted",
            "term": {
              "condition": "minecraft:entity_properties",
              "entity": "this",
              "predicate": {
                "equipment": {
                  "offhand":{
                    "items": ["minecraft:carrot_on_a_stick"],
                    "nbt": "{id:'cpp:red_force_of_fire'}"
                  }
                }
              }
            }
          }
        ]
      }
    }
  ]
}
</pre>

<p>如果模组含多个以胡萝卜钓竿为本体的物品需要探测，我们可以先判断是主手还是副手使用的，然后再分情形讨论。</p>
<pre class="file">cpp:use_cst</pre>
<pre>
execute as @s[predicate=<a href="#cpp/predicates/mainhand/carrot_on_a_stick">cpp:mainhand/carrot_on_a_stick</a>] run function <a href="#cpp/functions/use_cst_main">cpp:use_cst_main</a>
execute as @s[predicate=!<a href="#cpp/predicates/mainhand/carrot_on_a_stick">cpp:mainhand/carrot_on_a_stick</a>] run function <a href="#cpp/functions/use_cst_off">cpp:use_cst_off</a>
scoreboard players reset @s cppUseCSt
</pre>
<pre class="file" id="cpp/functions/use_cst_main">cpp:use_cst_main</pre>
<pre>
execute as @s[predicate=<a href="#cpp/predicates/mainhand/red_force_of_fire">cpp:mainhand/red_force_of_fire</a>] run function <a href="#cpp/functions/tools/red_force_of_fire">cpp:tools/red_force_of_fire</a>
execute as @s[predicate=<a href="#cpp/predicates/mainhand/blue_force_of_sky">cpp:mainhand/blue_force_of_sky</a>] run function <a href="#cpp/functions/tools/blue_force_of_sky">cpp:tools/blue_force_of_sky</a>
...
</pre>
<pre class="file" id="cpp/functions/use_cst_off">cpp:use_cst_off</pre>
<pre>
execute as @s[predicate=<a href="#cpp/predicates/offhand/red_force_of_fire">cpp:offhand/red_force_of_fire</a>] run function <a href="#cpp/functions/tools/red_force_of_fire">cpp:tools/red_force_of_fire</a>
execute as @s[predicate=<a href="#cpp/predicates/offhand/blue_force_of_sky">cpp:offhand/blue_force_of_sky</a>] run function <a href="#cpp/functions/tools/blue_force_of_sky">cpp:tools/blue_force_of_sky</a>
...
</pre>

<pre class="file" id="cpp/predicates/mainhand/carrot_on_a_stick">cpp/predicates/mainhand/carrot_on_a_stick.json</pre>
<pre>
{
  "condition": "minecraft:entity_properties",
  "entity": "this",
  "predicate": {
    "equipment": {
      "mainhand":{
        "items": ["minecraft:carrot_on_a_stick"]
      }
    }
  }
}
</pre>
<pre class="file" id="cpp/predicates/mainhand/red_force_of_fire">cpp/predicates/mainhand/red_force_of_fire.json</pre>
<pre>
{
  "condition": "minecraft:entity_properties",
  "entity": "this",
  "predicate": {
    "equipment": {
      "mainhand":{
        "nbt": "{id:'cpp:red_force_of_fire'}"
      }
    }
  }
}
</pre>

<pre class="file" id="cpp/predicates/offhand/red_force_of_fire">cpp/predicates/offhand/red_force_of_fire.json</pre>
<pre>
{
  "condition": "minecraft:entity_properties",
  "entity": "this",
  "predicate": {
    "equipment": {
      "offhand":{
        "nbt": "{id:'cpp:red_force_of_fire'}"
      }
    }
  }
}
</pre>

<p>如果需要的话，我们还可以手动模拟胡萝卜钓竿的耐久损耗。</p>
<pre class="file" id="cpp/functions/damage_cst">cpp:damage_cst</pre>
<pre>
execute as @s[predicate=<a href="#cpp/predicates/mainhand/carrot_on_a_stick">cpp:mainhand/carrot_on_a_stick</a>] run data modify storage cpp:damage Item set from entity @s SelectedItem
execute as @s[predicate=!<a href="#cpp/predicates/mainhand/carrot_on_a_stick">cpp:mainhand/carrot_on_a_stick</a>] run data modify storage cpp:damage Item set from entity @s Inventory[{Slot:-106b}]
function <a href="#cpp/functions/damage">cpp:damage</a>
execute if score #damage cppValue matches 26.. run data remove storage cpp:damage Item
setblock ~ 255 ~ shulker_box
data modify storage cpp:damage Item.Slot set value 0b
data modify block ~ 255 ~ Items append from storage cpp:damage Item
loot replace entity @s[predicate=<a href="#cpp/predicates/mainhand/carrot_on_a_stick">cpp:mainhand/carrot_on_a_stick</a>] weapon.mainhand 1 mine ~ 255 ~ tnt{drop_content:1b}
loot replace entity @s[predicate=!<a href="#cpp/predicates/mainhand/carrot_on_a_stick">cpp:mainhand/carrot_on_a_stick</a>] weapon.offhand 1 mine ~ 255 ~ tnt{drop_content:1b}
setblock ~ 255 ~ air
</pre>
<p class="noindent">处理耐久的函数 <code>cpp:damage</code> 见 <a href="#耐久处理">§10.3 耐久处理</a>。</p>

<p>投掷物如雪球、末影珍珠等可用于一次性右键工具，不同的物品有着各自的特点。投掷带自定义NBT标签的物品，对应的投掷物实体NBT <code>Item</code> 会包含这些NBT标签。注意，在1.14和更早版本，由于Mojang先消耗手持物再存储手持物信息，导致投掷最后一个物品时没有存储相应的 <code>Item</code> 信息，此时我们需要提前1刻存储玩家手持物信息方可。</p>
<p class="ex">扔出 <code>minecraft:experience_bottle{exXpNumber:99s}</code> 生成 <code>exXpNumber</code> 点经验值的经验球。</p>
<pre class="file">cpp:tick</pre>
<pre>
execute as @e[type=experience_bottle] if data entity @s Item.tag.exXpNumber at @s run function <a href="#cpp/functions/xp/throw">cpp:xp/throw</a>
</pre>
<pre class="file" id="cpp/functions/xp/throw">cpp:xp/throw</pre>
<pre>
summon experience_orb ~ ~ ~ {ags:["cpp_XpNumber"]}
execute store result entity @e[type=experience_orb,tag=cpp_XpNumber,limit=1,distance=..1] Value short 1 run data get entity @s Item.tag.cpp_XpNumber
tag @e[type=experience_orb,tag=cpp_XpNumber,limit=1,distance=..1] remove cpp_XpNumber
kill @s        
</pre>
<p>注意使用发射器发射该附魔之瓶仍然会表现如同普通附魔之瓶。</p>

<h2 id="食物">§5.3 食物</h2>

<p>我们一般要求食物的本体无合成用途，且和其它生物没有交互，饥饿值较低以便于通过饱和效果实现高饥饿值。由此，可选的有：</p>
<table><thead><tr><th>物品</th><th>优点</th><th>缺点</th></tr></thead><tbody>
<tr><td>曲奇</td>
  <td>饥饿值低，容易通过饱和效果实现至少2点饥饿值的食物。无合成用途。</td>
  <td>和鹦鹉可交互。</td>
</tr>
<tr><td>苹果</td>
  <td>饥饿值低，容易通过饱和效果实现至少4点饥饿值的食物。</td>
  <td>可用于合成金苹果。</td>
</tr>
<tr><td>熟鳕鱼</td>
  <td>饥饿值低，容易通过饱和效果实现至少5点饥饿值的食物。无合成用途。</td>
  <td>-</td>
</tr>
<tr><td>面包</td>
  <td>饥饿值低，容易通过饱和效果实现至少5点饥饿值的食物。无合成用途。和村民可交互。</td>
  <td>-</td>
</tr>
<tr><td>迷之炖菜</td>
  <td>容易实现状态效果。不可堆叠，食用后有碗。</td>
  <td>饥饿值过高，只能通过饱和效果实现至少8点饥饿值的食物。</td>
</tr>
</tbody></table>
<p class="ex">食用肉松面包回复10点饥饿值，并获得30秒的速度效果，且可扔给村民。</p>
<pre class="file" id="cpp/loot_tables/meat_floss_bread">cpp/loot_tables/meat_floss_bread.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:bread",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{display:{Name:'{\"translate\":\"item.ex.meat_floss_bread\"}'},id:'cpp:meat_floss_bread',CustomModelData:12970001}"
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<pre class="file" id="cpp/advancements/foods/meat_floss_bread">cpp/advancements/foods/meat_floss_bread.json</pre>
<pre>
{
  "criteria": {
    "meat_floss_bread": {
      "trigger": "minecraft:consume_item",
      "conditions": {
        "item": {
          "nbt": "{id:'cpp:meat_floss_bread'}"
        }
      }
    }
  },
  "rewards":{
    "function": "cpp:foods/meat_floss_bread"
  }
}
</pre>
<pre class="file" id="cpp/functions/foods/meat_floss_bread">cpp:foods/meat_floss_bread</pre>
<pre>
effect give @s saturation 1 4
effect give @s speed 30
advancement revoke @s only cpp:foods/meat_floss_bread
</pre>
<p class="noindent">这里，1秒的饱和IV可以恢复5点饥饿值，加上面包本身的5点，正好为10点。</p>

<p>如果我们想要制作不可堆叠类食物，可以为食物附加上随机的盔甲属性，且令其在 <code>chest</code> 栏位生效。由于一般食物无法放入玩家胸甲栏位，因此该属性并不会有实际效果。</p>
<pre class="file" id="cpp/loot_tables/colorful_vegetable">cpp/loot_tables/colorful_vegetable.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:cooked_cod",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{display:{Name:'{\"italic\":false,\"translate\":\"item.cpp.colorful_vegetable\"}'},id:'cpp:colorful_vegetable',CustomModelData:12970002,HideFlags:63}"
            },
            {
              "function": "minecraft:set_attributes",
              "modifiers": [
                {
                  "slot": "chest",
                  "name": "food_armor",
                  "attribute": "generic.armor",
                  "amount": 0,
                  "operation": "addition"
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<p>更为简便的做法是使用迷之炖菜，注意会剩下碗。迷之炖菜可以自带药水效果，无需进度和函数来额外实现药水效果，但由于只能设置为1级，因此额外的饥饿值仍然需要进度。</p>
<p class="ex">食用缤纷菜蔬回复6点饥饿值，并获得30秒的跳跃提升效果。</p>
<pre class="file">cpp/loot_tables/colorful_vegetable.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:suspicious_stew",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{display:{Name:'{\"translate\":\"item.ex.colorful_vegetable\"}',Lore:['{\"translate\":\"lore.ex.leap\"}']},id:'cpp:colorful_vegetable',CustomModelData:12970002,Effects:[{EffectDuration:600,EffectId:8b}]}"
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<p>对于想要使用饥饿效果来降低饥饿值的情形，注意饥饿效果会先消耗饱食度，且如果玩家食用后饥饿值已满，还需要通过记分板来实时检测上一刻玩家的饥饿值以确定当前的饥饿值应当为多少。因此实现较为繁琐，这里便不做详解。</p>

<h2 id="药水">§5.4 药水</h2>
<p>我们使用药水来实现自定义的药水效果。</p>
<p class="ex">饮用潮汐药水后获得8分钟的潮涌之力效果。</p>
<pre class="file" id="cpp/loot_tables/potion_of_tide">cpp/loot_tables/potion_of_tide.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:potion",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{display:{Name:'{\"translate\":\"item.ex.potion_of_tide\"}'},id:"cpp:potion_of_tide",CustomPotionColor:1950417,CustomPotionEffects:[{Id:29b,Amplifier:0b,Duration:9600}]}"
            }
          ]
        }
      ]
    }
  ]
}
</pre>

<p>如果我们想要药水可以堆叠，可以使用食物(64堆叠数)或蜂蜜瓶(16堆叠数)来实现，但要注意它们可以恢复饥饿值，且可能可参与合成。我们需要手动为食物加上显示药水效果的<code>Lore</code>。</p>
<p class="ex">饮用天空药水(16堆叠数)后回复6点饥饿值，并获得6分钟的速度II和6分钟的缓降效果。</p>
<pre class="file" id="cpp/loot_tables/agentia_of_sky">cpp/loot_tables/agentia_of_sky.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:honey_bottle",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{display:{Name:'{\"translate\":\"item.ex.agentia_of_sky\"}',Lore:['[{\"translate\":\"effect.minecraft.speed\",\"italic\":\"false\",\"color\":\"blue\"},{\"text\":\" II (6:00)\"}]','[{\"translate\":\"effect.minecraft.slow_falling\",\"italic\":\"false\",\"color\":\"blue\"},{\"text\":\" (6:00)\"}]','\" \"','{\"translate\":\"potion.whenDrank\",\"italic\":\"false\"}','[{\"text\":\"+40% \",\"italic\":\"false\",\"color\":\"blue\"},{\"translate\":\"attribute.name.generic.movementSpeed\"}]']},id:'cpp:agentia_of_sky',CustomModelData:12970101}"
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<pre class="file" id="cpp/advancements/agentia_of_sky">cpp/advancements/agentia_of_sky.json</pre>
<pre>
{
  "criteria": {
    "consume": {
      "trigger": "minecraft:consume_item",
      "conditions": {
        "item": {
          "nbt": "{id:'cpp:agentia_of_sky'}"
        }
      }
    }
  },
  "rewards":{
    "function": "cpp:potion/agentia_of_sky"
  }
}
</pre>
<pre class="file" id="cpp/functions/potion/agentia_of_sky">cpp:potion/agentia_of_sky</pre>
<pre>
effect give @s speed 360 1
effect give @s slow_falling 360
advancement revoke @s only cpp:potion/agentia_of_sky
</pre>

<h2 id="自定义状态效果">§5.5 自定义状态效果</h2>
<p>原版定义新的状态效果是不可能的，但是我们可以通过进度来模拟食用特定物品后的效果。我们使用记分板来记录时长，模拟药水的颗粒效果，并在<code>actionbar</code>显示剩余时长。</p>
<p class="ex">饮用泥土药水后获得12分钟的隐身和12分钟的连锁效果，这里我们不涉及实际效果的实现。</p>
<pre class="file" id="cpp/loot_tables/agentia_of_dirt">cpp/loot_tables/agentia_of_dirt.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:honey_bottle",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{display:{Name:'{\"translate\":\"item.ex.agentia_of_dirt\"}',Lore:['[{\"translate\":\"effect.minecraft.invisibility\",\"italic\":\"false\",\"color\":\"blue\"},{\"text\":\" (12:00)\"}]','[{\"translate\":\"lore.ex.chain\",\"italic\":\"false\",\"color\":\"blue\"},{\"text\":\" (12:00)\"}]']},id:'cpp:agentia_of_dirt',CustomModelData:12970104}"
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<pre class="file" id="cpp/advancements/agentia_of_dirt">cpp/advancements/agentia_of_dirt.json</pre>
<pre>
{
  "criteria": {
    "consume": {
      "trigger": "minecraft:consume_item",
      "conditions": {
        "item": {
          "nbt": "{id:'cpp:agentia_of_dirt'}"
        }
      }
    }
  },
  "rewards":{
    "function": "cpp:potion/agentia_of_dirt"
  }
}
</pre>
<pre class="file" id="cpp/functions/potion/agentia_of_dirt">cpp:potion/agentia_of_dirt</pre>
<pre>
effect give @s invisibility 720
execute unless score @s cppChainTick matches 14400.. run scoreboard players set @s cppChainTick 14400
advancement revoke @s only cpp:potion/agentia_of_dirt
</pre>
<pre class="file">cpp:tick</pre>
<pre>
execute as @a[scores={cppChainTick=1..}] at @s anchored eyes run function <a href="#cpp/functions/chain/type">cpp:chain/type</a>
</pre>
<pre class="file" id="cpp/functions/chain/type">cpp:chain/type</pre>
<pre>
execute positioned ^ ^ ^0.2 run particle entity_effect ~ ~-1 ~ 0.734375 0.37890625 0.3046875 1 0
scoreboard players remove @s cppChainTick 1
[省略实际效果部分]
</pre>
<p class="noindent">我们使用周期为20刻的低频来显示剩余时长。</p>
<pre class="file">cpp:load</pre>
<pre>
function <a href="#cpp/functions/tick20">cpp:tick20</a>
</pre>
<pre class="file">cpp:tick20</pre>
<pre>
execute as @a[scores={cppChainTick=1..}] run function <a href="#cpp/functions/chain/showtime">cpp:chain/showtime</a>
schedule function <a href="#cpp/functions/tick20">cpp:tick20</a> 20t
</pre>
<pre class="file" id="cpp/functions/chain/showtime">cpp:chain/showtime</pre>
<pre>
scoreboard players operation #min cppValue = @s cppChainTick
scoreboard players operation #min cppValue /= #20 cppValue
scoreboard players operation #sec cppValue = #min cppValue
scoreboard players operation #min cppValue /= #60 cppValue
scoreboard players operation #sec cppValue %= #60 cppValue
execute as @s[scores={cppChainTick=20..}] if score #sec cppValue matches 10.. run title @s actionbar [{"translate":"title.effect.chain"},{"score":{"name":"#min","objective":"cppValue"},"color":"gray"},{"text":":"},{"score":{"name":"#sec","objective":"cppValue"},"color":"gray"}]
execute as @s[scores={cppChainTick=20..}] if score #sec cppValue matches ..9 run title @s actionbar [{"translate":"title.effect.chain"},{"score":{"name":"#min","objective":"cppValue"},"color":"gray"},{"text":":"},{"text":"0","color":"gray"},{"score":{"name":"#sec","objective":"cppValue"},"color":"gray"}]
title @s[scores={cppChainTick=..19}] actionbar [{"text":" "}]
</pre>

<p>我们无法在背包页面显示图标和时长，但是我们可以在特定分辨率下在右上角显示图标。这里需要使用<a href="3.8_字体">§3.8 字体</a>的负空格字体技巧。我们假设当前分辨率为<code>1920×1080</code>，通过试验得知使用<code>actionbar</code>占据整个右上角需要的大小为<code>480×182</code>，因此我们使用<code>298</code>像素宽的空格和<code>182×182</code>的图案。</p>
<pre class="file" id="assets/cpp/font/default">assets/cpp/font/default.json</pre>
<pre>
{
  "providers": [
    {
      "type": "bitmap",
      "file": "cpp:font/space.png",
      "ascent": -32768,
      "height": 297,
      "chars": ["1"]
    },
    {
      "type": "bitmap",
      "file": "cpp:font/chain.png",
      "height": 182,
      "ascent": 182,
      "chars": ["2"]
    }
  ]
}
</pre>
<p class="noindent">其中文件 <code>assets/cpp/textures/font/space.png</code> 为 <code>1×1</code> 的透明文件，<code>assets/cpp/textures/font/chain.png</code> 为 <code>182×182</code> 的文件，右上角为需要显示的状态效果图案。我们使用自定义的字体以避免占据原版字符。</p>
<figure>
  <img src="items/space.png" alt="空格纹理" />
  <figcaption>图5.1 空格纹理</figcaption>
</figure>

<figure>
  <img src="items/chain.png" alt="状态效果纹理" />
  <figcaption>图5.2 状态效果纹理</figcaption>
</figure>

<pre class="file">cpp:chain/showtime</pre>
<pre>
title @s actionbar {"font":"cpp:default","text":"12"}
</pre>

<figure>
  <img src="items/chain_effect.png" alt="自定义状态效果" />
  <figcaption>图5.3 自定义状态效果</figcaption>
</figure>
<p>状态效果即将结束时的闪烁效果也可以类似实现，这里不再赘述。</p>


<h2 id="头饰">§5.6 头饰</h2>
<p>我们使用雕刻过的南瓜来实现头饰。</p>
<p class="ex">可佩戴在头部的花环。</p>
<pre class="file" id="cpp/loot_tables/garland">cpp/loot_tables/garland.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:carved_pumpkin",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{display:{Name:'{\"translate\":\"item.ex.garland\"}'},id:'cpp:garland',CustomModelData:12970124,exHatSlot:'hand'}"
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<p class="noindent">由于雕刻过的南瓜可以放置，为了避免我们需要处理放置方块事件，细节见 <a href="6_方块设计">§6 方块设计</a>。我们假设已探测到南瓜位置，且玩家放置的方块的NBT信息已存储在存储区<code>cpp:block Item</code>，我们对其进行破坏并生成原物品。</p>
<pre class="file" id="cpp/block/carved_pumpkin">cpp/block/carved_pumpkin.json</pre>
<pre>
setblock ~ ~ ~ air
kill @s
summon item ~ ~ ~ {Item:{id:"minecraft:firework_star",Count:1b,tag:{CustomModelData:12971000}},Tags:["cpp_temp"]}
data modify entity @e[type=item,tag=cpp_temp,distance=..0.1,limit=1] Item set from storage cpp:block Item
tag @e[type=item,tag=cpp_temp,distance=..0.1,limit=1] remove cpp_temp
</pre>

<p>我们将资源包内文件 <code>minecraft/textures/misc/pumpkinblur.png</code> 设置为完全透明的图片以清除雕刻过的南瓜戴在头上的视野限制效果。</p>
<p>对于头饰而言，我们希望其像盔甲一样在背包物品栏显示为物品的平面纹理，而在玩家头部显示为立体模型。因此我们需要两套模型，并处理物品进入玩家头部和手部的事件，见<a href="https://www.mcbbs.net/thread-833056-1-1.html">【1.14】物品头部/背包/手持显示不同纹理/模型</a>。</p>

<pre class="file" id="minecraft/models/item/carved_pumpkin">minecraft/models/item/carved_pumpkin.json</pre>
<pre>
{
  "parent": "block/orientable",
  "textures": {
    "top": "block/pumpkin_top",
    "front": "block/carved_pumpkin",
    "side": "block/pumpkin_side"
  },
  "overrides": [
    { "predicate": { "custom_model_data": 12970024 }, "model": "cpp:decor/garland"},
    { "predicate": { "custom_model_data": 12970124 }, "model": "cpp:decor/garland1"}
  ]
}
</pre>
<p>在手部时，为普通物品模型。</p>
<pre class="file" id="cpp/models/decor/garland1">cpp/models/decor/garland1.json</pre>
<pre>
{
  "parent": "item/generated",
  "textures": {
    "layer0": "cpp:decor/garland_item"
  }
}
</pre>
<figure>
  <img src="items/garland_item.png" alt="花环物品纹理" />
  <figcaption>图5.4 花环物品纹理</figcaption>
</figure>

<p>在头部时，我们将其在背包的显示旋转使得只能看到方块底部，而底部纹理为对应的普通物品纹理。其它5个面用于显示花环的立体纹理模型。</p>
<pre class="file" id="cpp/models/decor/garland">cpp/models/decor/garland.json</pre>
<pre>
{
  "parent": "cpp:decor/hat",
  "textures": {
    "hat": "cpp:decor/garland",
    "item": "cpp:decor/garland_item"
  }
}
</pre>
<pre class="file" id="cpp/models/decor/hat">cpp/models/decor/hat.json</pre>
<pre>
{
  "parent": "block/block",
  "display": {
    "gui": {
      "rotation": [ -90, 0, 0 ]
    }
  },
  "elements": [
    {
      "from": [ 0, 0, 0 ],
      "to": [ 16, 16, 16 ],
      "faces": {
        "down":  { "uv": [ 0, 0,16,16 ], "texture": "#item", "cullface": "down" },
        "up":     { "uv": [ 4, 0, 8, 4 ], "texture": "#hat", "cullface": "up" },
        "north": { "uv": [ 4, 4, 8, 8 ], "texture": "#hat", "cullface": "north" },
        "south": { "uv": [12, 4,16, 8 ], "texture": "#hat", "cullface": "south" },
        "west":  { "uv": [ 8, 4,12, 8 ], "texture": "#hat", "cullface": "west" },
        "east":  { "uv": [ 0, 4, 4, 8 ], "texture": "#hat", "cullface": "east" }
      }
    }
  ]
}
</pre>
<figure>
  <img src="items/garland.png" alt="花环方块纹理" />
  <figcaption>图5.5 花环方块纹理</figcaption>
</figure>

<pre class="file" id="cpp/predicates/mainhand_hat">cpp/predicates/mainhand_hat.json</pre>
<pre>
{
  "condition": "minecraft:entity_properties",
  "entity": "this",
  "predicate": {
    "equipment": {
      "mainhand":{
        "items": ["minecraft:carved_pumpkin"],
        "nbt": "{exHatSlot:'head'}"
      }
    }
  }
}
</pre>
<pre class="file" id="cpp/loot_tables/offhand_hat">cpp/loot_tables/offhand_hat.json</pre>
<pre>
{
  "condition": "minecraft:entity_properties",
  "entity": "this",
  "predicate": {
    "equipment": {
      "offhand":{
        "items": ["minecraft:carved_pumpkin"],
        "nbt": "{exHatSlot:'head'}"
      }
    }
  }
}
</pre>
<pre class="file" id="cpp/loot_tables/head_hat">cpp/loot_tables/head_hat.json</pre>
<pre>
{
  "condition": "minecraft:entity_properties",
  "entity": "this",
  "predicate": {
    "equipment": {
      "head":{
        "items": ["minecraft:carved_pumpkin"],
        "nbt": "{exHatSlot:'hand'}"
      }
    }
  }
}
</pre>
<pre class="file">cpp:tick</pre>
<pre>
execute as @a[predicate=<a href="#cpp/predicates/mainhand_hat">cpp:mainhand_hat</a>] run function <a href="#cpp/functions/decor/mainhand_hat">cpp:decor/mainhand_hat</a>
execute as @a[predicate=<a href="#cpp/predicates/offhand_hat">cpp:offhand_hat</a>] run function <a href="#cpp/functions/decor/offhand_hat">cpp:decor/offhand_hat</a>
execute as @a[predicate=<a href="#cpp/predicates/head_hat">cpp:head_hat</a>] run function <a href="#cpp/functions/decor/head_hat">cpp:decor/head_hat</a>
</pre>
<pre class="file" id="cpp/functions/decor/mainhand_hat">cpp:decor/mainhand_hat</pre>
<pre>
setblock ~ 255 ~ shulker_box{Items:[{Slot:0b,id:"minecraft:carved_pumpkin",Count:1b}]}
data modify block ~ 255 ~ Items[0] merge from entity @s SelectedItem
execute store result score #temp cppValue run data get block ~ 255 ~ Items[0].tag.CustomModelData
execute store result block ~ 255 ~ Items[0].tag.CustomModelData int 1 run scoreboard players add #temp cppValue 100
data modify block ~ 255 ~ Items[0].tag.exHatSlot set value "hand"
loot replace entity @s weapon.mainhand 1 mine ~ 255 ~ tnt{drop_content:1b}
setblock ~ 255 ~ air
</pre>
<pre class="file" id="cpp/functions/decor/off_hat">cpp:decor/off_hat</pre>
<pre>
setblock ~ 255 ~ shulker_box{Items:[{Slot:0b,id:"minecraft:carved_pumpkin",Count:1b}]}
data modify block ~ 255 ~ Items[0].Count set from entity @s Inventory[{Slot:-106b}].Count
data modify block ~ 255 ~ Items[0].tag set from entity @s Inventory[{Slot:-106b}].tag
execute store result score #temp cppValue run data get block ~ 255 ~ Items[0].tag.CustomModelData
execute store result block ~ 255 ~ Items[0].tag.CustomModelData int 1 run scoreboard players add #temp cppValue 100
data modify block ~ 255 ~ Items[0].tag.exHatSlot set value "hand"
loot replace entity @s weapon.offhand 1 mine ~ 255 ~ tnt{drop_content:1b}
setblock ~ 255 ~ air
</pre>
<pre class="file" id="cpp/functions/decor/head_hat">cpp:decor/head_hat</pre>
<pre>
setblock ~ 255 ~ shulker_box{Items:[{Slot:0b,id:"minecraft:carved_pumpkin",Count:1b}]}
data modify block ~ 255 ~ Items[0].Count set from entity @s Inventory[{Slot:103b}].Count
data modify block ~ 255 ~ Items[0].tag set from entity @s Inventory[{Slot:103b}].tag
execute store result score #temp cppValue run data get block ~ 255 ~ Items[0].tag.CustomModelData
execute store result block ~ 255 ~ Items[0].tag.CustomModelData int 1 run scoreboard players remove #temp cppValue 100
data modify block ~ 255 ~ Items[0].tag.exHatSlot set value "head"
loot replace entity @s armor.head 1 mine ~ 255 ~ tnt{drop_content:1b}
setblock ~ 255 ~ air
</pre>
<p class="noindent">这里我们使用了潜影盒战利品表技巧来修改玩家背包物品，见 <a href="#战利品表">§2.5 战利品表</a>。</p>

<h2 id="盔甲">§5.7 盔甲</h2>
<p>头饰通过添加属性可以实现为头盔，但是胸甲、护腿和靴子无法通过资源包和数据包来修改其穿戴在身上时的显示纹理，因为这三个栏位只接受相应类别的物品。我们只能通过诸如修改皮革盔甲颜色来达到视觉上的不同。例如：绿宝石靴子穿在脚上时，增加5点盔甲、2点盔甲韧性、4点生命值。注意，这个靴子和耐久和皮革靴子一样低。</p>

<pre class="file" id="cpp/loot_tables/emerald_boots">cpp/loot_tables/emerald_boots.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:leather_boots",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{display:{Name:'{\"translate\":\"item.ex.emerald_boots\"}',color:1564002},id:'cpp:emerald_boots'}"
            },
            {
              "function": "minecraft:set_attributes",
              "modifiers": [
                {
                  "amount": 3,
                  "name": "cpp_armor",
                  "attribute": "generic.armor",
                  "operation": "addition","slot": "feet"
                },
                {
                  "amount": 2,
                  "name": "cpp_armorToughness",
                  "attribute": "generic.armorToughness",
                  "operation": "addition",
                  "slot": "feet"},
                {
                  "amount": 4,
                  "name": "cpp_maxHealth",
                  "attribute": "generic.maxHealth",
                  "operation": "addition",
                  "slot": "feet"
                }        
              ]
            }
          ]
        }
      ]
    }
  ]
}
</pre>

<h2 id="工具和武器">§5.8 工具和武器</h2>
<p>工具和武器同样可以通过原版工具和武器修改得到。例如：使用玻璃镐挖掘玻璃时，玻璃掉落自身。</p>

<pre class="file" id="cpp/loot_tables/glass_pickaxe">cpp/loot_tables/glass_pickaxe.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:stone_pickaxe",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{display:{Name:'{\"translate\":\"item.ex.glass_pickaxe\"}'},id:'cpp:glass_pickaxe',CustomModelData:12970001}"
            }
          ]
        }
      ]
    }
  ]
}
</pre>

<p>我们对所有的玻璃和玻璃板的战利品表进行修改。</p>
<pre class="file" id="minecraft/loot_tables/blocks/red_stained_glass">minecraft/loot_tables/blocks/red_stained_glass.json</pre>
<pre>
{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "conditions": [
        {
          "condition": "minecraft:reference",
          "name": "cpp:drop_glass"
        }
      ],
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:red_stained_glass"
        }
      ]
    }
  ]
}
</pre>

<pre class="file" id="cpp/predicates/drop_glass">cpp/predicates/drop_glass.json</pre>
<pre>
{
  "condition": "minecraft:alternative",
  "terms": [
    {
      "condition": "minecraft:match_tool",
      "predicate": {
        "enchantments": [
          {
            "enchantment": "minecraft:silk_touch",
            "levels": {
              "min": 1
            }
          }
        ]
      }
    },
    {
      "condition": "minecraft:match_tool",
      "predicate": {
        "nbt": "{id:'cpp:glass_pickaxe'}"
      }
    }
  ]
}
</pre>

<p>这些物品的耐久都是不可修改的，但是我们可以将其设置为不可破坏，然后每次使用后模拟耐久降低的过程。</p>

<pre class="file">cpp:load</pre>
<pre>
scoreboard objectives add exUseSPick minecraft.used:minecraft.stone_pickaxe
</pre>
<pre class="file">cpp:tick</pre>
<pre>
execute as @s[scores={exUseSPick=1..}] run function <a href="#cpp/functions/tools/glass_pickaxe/reset">cpp:tools/glass_pickaxe/reset</a>
</pre>
<pre class="file" id="cpp/functions/tools/glass_pickaxe/reset">cpp:tools/glass_pickaxe/reset</pre>
<pre>
scoreboard players reset @s exUseSPick
execute as @s[nbt={SelectedItem:{tag:{id:"cpp:glass_pickaxe"}}}] run function <a href="#cpp/functions/tools/glass_pickaxe/damage">cpp:tools/glass_pickaxe/damage</a>
</pre>
<pre class="file" id="cpp/functions/tools/glass_pickaxe/damage">cpp:tools/glass_pickaxe/damage</pre>
<pre>
data modify storage cpp:temp Item set from entity @s SelectedItem
function <a href="#cpp/functions/damage_tool">cpp:damage_tool</a>
execute if score #damage cppValue matches 99.. run data remove storage cpp:temp Item
setblock ~ 255 ~ shulker_box
data modify block ~ 255 ~ Items append from storage cpp:temp Item
loot replace entity @s weapon.mainhand 1 mine ~ 255 ~ tnt{drop_content:1b}
setblock ~ 255 ~ air
</pre>
<p class="noindent">函数 <code>cpp:damage_tool</code> 见<a href="右键交互">§5.2 右键交互</a>，这里省略。这里我们使用 <a href="#修改玩家背包">§10.2 修改玩家背包</a>中的潜影盒战利品表来将物品输出到玩家手中。</p>


<h2 id="画">§5.9 画</h2>
<p>我们使用指定内含物的物品展示框来实现自定义的画。例如：放置经典画作后显示一幅画，右键可以切换。</p>
<p>我们为烟火之星 <code>CustomModelData</code> 为 <code>12974001-12974100</code> 指定100个平面画模型。</p>
<pre class="file" id="cpp/loot_tables/classical_painting">cpp/loot_tables/classical_painting.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:item_frame",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{display:{Name:'{\"translate\":\"item.ex.classical_painting\"}'},id:'cpp:classical_painting',CustomModelData:12970002,EntityTag:{Item:{id:'minecraft:firework_star',Count:1b,tag:{CustomModelData:12974001,exClear:1b}},Tags:['cpp_item_frame_classical_painting','cpp_special_item_frame']}}"
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<pre class="file">cpp:tick</pre>
<pre>
execute as @e[type=item_frame,tag=cpp_special_item_frame] at @s run function <a href="#cpp/functions/item_frame/special">cpp:item_frame/special</a>
</pre>
<pre class="file" id="cpp/functions/item_frame/special">cpp:item_frame/special</pre>
<pre>
execute as @s[nbt={Facing:0b}] if block ~ ~1 ~ #cpp:fluid run function <a href="#cpp/functions/item_frame/special_break">cpp:item_frame/special_break</a>
execute as @s[nbt={Facing:1b}] if block ~ ~-1 ~ #cpp:fluid run function <a href="#cpp/functions/item_frame/special_break">cpp:item_frame/special_break</a>
execute as @s[nbt={Facing:2b}] if block ~ ~ ~1 #cpp:fluid run function <a href="#cpp/functions/item_frame/special_break">cpp:item_frame/special_break</a>
execute as @s[nbt={Facing:3b}] if block ~ ~ ~-1 #cpp:fluid run function <a href="#cpp/functions/item_frame/special_break">cpp:item_frame/special_break</a>
execute as @s[nbt={Facing:4b}] if block ~1 ~ ~ #cpp:fluid run function <a href="#cpp/functions/item_frame/special_break">cpp:item_frame/special_break</a>
execute as @s[nbt={Facing:5b}] if block ~-1 ~ ~ #cpp:fluid run function <a href="#cpp/functions/item_frame/special_break">cpp:item_frame/special_break</a>
execute unless block ~ ~ ~ #cpp:fluid run function <a href="#cpp/functions/item_frame/special_break">cpp:item_frame/special_break</a>
execute unless data entity @s Item.id run function <a href="#cpp/functions/item_frame/special_break">cpp:item_frame/special_break</a>
execute as @s[nbt={ItemRotation:1b}] run function <a href="#cpp/functions/item_frame/special_rot">cpp:item_frame/special_rot</a>
</pre>
<p class="noindent">方块标签 <code>cpp:fluid</code> 见 <a href="#标签">§2.10 标签</a>。</p>
<pre class="file" id="cpp/functions/item_frame/special_break">cpp:item_frame/special_break</pre>
<pre>
execute as @s[tag=cpp_item_frame_classical_painting] run loot spawn ~ ~ ~ loot cpp:classical_painting
kill @s
</pre>
<pre class="file" id="cpp/functions/item_frame/special_rot">cpp:item_frame/special_rot</pre>
<pre>
execute store result entity @s Item.tag.CustomModelData int 1.00000008 run data get entity @s Item.tag.CustomModelData
data modify entity @s ItemRotation set value 0b
data modify entity @s[nbt={Item:{tag:{CustomModelData:12974101}}}] Item.tag.CustomModelData set value 12974001
</pre>

<p>自定义地图也可以用来显示自定义的图案，这个方法可避免使用资源包，但需将<code>data</code>文件与数据包一同发布。首先确定好长宽比例，然后使用<a href="https://mc-map.djfun.de">MC Map Item Tool</a>在线转换。注意这个网站生成的地图已经不符合1.14+版本的地图格式了，请在本地生成锁定图案的地图后将该网站生成的地图的<code>colors</code>这个NBT复制过来。这些地图文件位于<code>世界名称/data</code>文件夹。发布时，将其和数据包一同发布。使用命令 <code>give @s minecraft:filled_map{map:[数值]}</code> 获取相应地图。选择负数的自定义地图的编号，或者手动将<code>data</code>文件夹中的<code>idcounts</code>调大，可避免和玩家在游戏内生成的地图编号冲突。</p>


<h1 id="方块设计">§6 方块设计</h1>
<p>原版模组无法添加方块，一般的做法是修改方块物品的 <code>CustomModelData</code>的模型后，在方块位置生成用于显示的实体。参考</p>
<ul>
  <li><a href="https://www.mcbbs.net/thread-771638-1-1.html">使用局部坐标做到找到玩家指的地方</a></li>
  <li><a href="https://www.mcbbs.net/thread-825546-1-1.html">完美的自定义方块堆叠</a></li>
  <li><a href="https://www.mcbbs.net/thread-824528-1-1.html">自定义方块(玩家头颅) </a></li>
</ul>
<p>实体一般使用头戴相应物品的盔甲架或者存储有相应物品的物品展示框或荧光物品展示框。相比于盔甲架，物品展示框的优点是：</p>
<ul>
  <li>渲染卡顿更小；</li>
  <li>使用荧光物品展示框可以避免对盔甲架修改 <code>Fire</code> 来保持其被实体方块覆盖时不变黑。</li>
</ul>
<p>缺点是：</p>
<ul>
  <li>不可自由旋转，例如用于显示地面的告示牌模型就相对麻烦一点；</li>
  <li>不可自由移动，只能位于整数坐标处；</li>
  <li>不可使用物品标签谓词，盔甲架可以将物品复制到主副手来判断其是否属于某物品标签，而物品展示框不行；</li>
  <li>不可使用工具进行 <code>loot mine/kill</code>；</li>
  <li>拥有CustomName时会显示物品名称。</li>
</ul>
<p>在这些缺点不影响时，我们更建议使用物品展示框。本节中我们以盔甲架为例。首先我们根据 <a href="#物品设计">§5 物品设计</a>来将方块对应的物品设计好，然后我们需要定位到方块所在位置。我们使用进度判断玩家放置了某物品，然后剥夺进度，获取该方块位置。由于玩家可以紧靠其它不完整方块来放置，这会导致该方块位置不一定在玩家视线上。一种做法是记录所有方块的碰撞箱，然后判断玩家视线与何方块的何面相交，从而得到方块位置，见<a href="#https://www.mcbbs.net/thread-919112-1-1.html">超精准的射线追踪碰撞检测器</a>。另一种在放弃精准度的前提下，我们可以将视线向相邻6个位置移动一格检测。为了简便，我们采用第二种做法。</p>
<p>最后，我们在方块位置放置盔甲架。我们需要判断玩家是主手还是副手放置的，并将相应的物品信息复制到盔甲架头部。不直接使用 <code>loot</code> 命令复制到盔甲架头部是为了在之后的破坏事件中保留原物品的额外信息，例如玩家重命名的名称等。反之，若我们不希望保留这些额外信息，则可以直接使用 <code>loot</code> 命令输入到盔甲架头部。</p>
<p>对于特殊的方块物品，我们需要对盔甲架进行预处理或调整，例如</p>
<ul>
  <li>有朝向的我们需要根据玩家朝向来放置不同朝向的方块。</li>
  <li>告示牌我们需要根据朝向来调整盔甲架位置和朝向。</li>
  <li>树苗花草作物我们需要放置后调整 <code>CustomModelData</code>，因为一般手持为平面纹理模型。</li>
  <li>需要添加额外标签以便于处理的。</li>
</ul>

<h2 id="视线追踪法">§6.1 视线追踪法</h2>
<p>我们使用递归向前来获取方块位置。</p>
<pre class="file" id="cpp/advancements/blocks/acacia_leaves">cpp/advancements/blocks/acacia_leaves.json</pre>
<pre>
{
  "criteria": {
    "acacia_leaves": {
      "trigger": "minecraft:placed_block",
      "conditions": {
        "block": "minecraft:acacia_leaves"
      }
    }
  },
  "rewards": {
    "function": "cpp:blocks/acacia_leaves/reset"
  }
}
</pre>
<pre class="file" id="cpp/functions/blocks/acacia_leaves/reset">cpp:blocks/acacia_leaves/reset</pre>
<pre>
advancement revoke @s only cpp:blocks/acacia_leaves
execute as @s[predicate=<a href="#cpp/predicates/mainhand/acacia_leaves">cpp:mainhand/acacia_leaves</a>] run data modify storage cpp:_ weapon.Item set from entity @s SelectedItem
execute as @s[predicate=!cpp:mainhand/acacia_leaves] run data modify storage cpp:_ weapon.Item set from entity @s Inventory[{Slot:-106b}]
execute store result score #put_block_cmd cppValue run data get storage cpp:_ weapon.Item.tag.CustomModelData
execute if score #put_block_cmd cppValue matches 12970000..12979999 at @s anchored eyes positioned ^ ^ ^ run function <a href="#cpp/functions/blocks/acacia_leaves/locate">cpp:blocks/acacia_leaves/locate</a>
</pre>
<pre class="file" id="cpp/functions/blocks/acacia_leaves/locate">cpp:blocks/acacia_leaves/locate</pre>
<pre>
function <a href="#cpp/functions/blocks/acacia_leaves/ray">cpp:blocks/acacia_leaves/ray</a>
execute unless entity @e[type=marker,distance=..7,tag=cpp_block_pos] positioned ~ ~1 ~ run function <a href="#cpp/functions/blocks/acacia_leaves/ray">cpp:blocks/acacia_leaves/ray</a>
execute unless entity @e[type=marker,distance=..8,tag=cpp_block_pos] positioned ~ ~-1 ~ run function <a href="#cpp/functions/blocks/acacia_leaves/ray">cpp:blocks/acacia_leaves/ray</a>
execute unless entity @e[type=marker,distance=..8,tag=cpp_block_pos] positioned ~1 ~ ~ run function <a href="#cpp/functions/blocks/acacia_leaves/ray">cpp:blocks/acacia_leaves/ray</a>
execute unless entity @e[type=marker,distance=..8,tag=cpp_block_pos] positioned ~-1 ~ ~ run function <a href="#cpp/functions/blocks/acacia_leaves/ray">cpp:blocks/acacia_leaves/ray</a>
execute unless entity @e[type=marker,distance=..8,tag=cpp_block_pos] positioned ~ ~ ~1 run function <a href="#cpp/functions/blocks/acacia_leaves/ray">cpp:blocks/acacia_leaves/ray</a>
execute unless entity @e[type=marker,distance=..8,tag=cpp_block_pos] positioned ~ ~ ~-1 run function <a href="#cpp/functions/blocks/acacia_leaves/ray">cpp:blocks/acacia_leaves/ray</a>
execute at @e[type=marker,distance=..8,tag=cpp_block_pos,sort=nearest,limit=1] align xyz positioned ~0.5 ~ ~0.5 run function <a href="#cpp/functions/blocks/acacia_leaves/put">cpp:blocks/acacia_leaves/put</a>
kill @e[type=marker,distance=..10,tag=cpp_block_pos]
</pre>
<pre class="file" id="cpp/functions/blocks/acacia_leaves/ray">cpp:blocks/acacia_leaves/ray</pre>
<pre>
execute if entity @s[distance=..10] if block ~ ~ ~ acacia_leaves align xyz positioned ~0.5 ~ ~0.5 unless entity @e[type=armor_stand,distance=..0.5] run summon marker ~ ~ ~ {Tags:["cpp_block_pos"]}
execute if entity @s[distance=..10] unless entity @e[type=marker,distance=..6,tag=cpp_block_pos] positioned ^ ^ ^0.005 run function <a href="#cpp/functions/blocks/acacia_leaves/ray">cpp:blocks/acacia_leaves/ray</a>
</pre>
<pre class="file" id="cpp/functions/blocks/acacia_leaves/put">cpp:blocks/acacia_leaves/put</pre>
<pre>
data modify storage cpp:_ weapon.Item.Count set value 1b
summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Small:1b,Marker:1b,NoGravity:1b,DisabledSlots:7967,Fire:32767s,Tags:["cpp_leaves","cpp_need_fire"]}
execute as @e[type=armor_stand,tag=cpp_leaves,distance=..0.1,limit=1] run function <a href="#cpp/functions/blocks/acacia_leaves/tag">cpp:blocks/acacia_leaves/tag</a>
</pre>
<pre class="file" id="cpp/functions/blocks/acacia_leaves/tag">cpp:blocks/acacia_leaves/tag</pre>
<pre>
execute if score #put_block_cmd cppValue matches 12970301 run tag @s add cpp_fruit_leaves
execute if score #put_block_cmd cppValue matches 12970302 run tag @s add cpp_ore_leaves
execute if score #put_block_cmd cppValue matches 12970303 run tag @s add cpp_wool_leaves
execute if score #put_block_cmd cppValue matches 12970304 run tag @s add cpp_sakura_leaves
data modify entity @s ArmorItems[3] set from storage cpp:_ weapon.Item
</pre>

<p>注意到我们在视线追踪是进行了当前方块内是否已有盔甲架的判断。这在处理完整方块时是可以省略的，但是对于非完整方块，视线上可能已经有之前放置过的模组物品对应的盔甲架，使用该项判断可以避免在一个格子内放置两个盔甲架，而忽略掉后放的方块。</p>
<p>如果为了避免误伤玩家放置的盔甲架，可以通过判断盔甲架是否拥有某特定 <code>tag</code>。然而，这个做法仍然对其它模组的方块无效，因为你无法知道其它模组使用了何种标签。更进一步我们可以判断当前方块处是否有头部佩戴拥有 <code>tag.id</code> 物品的盔甲架。具体代码读者可自行实现。</p>

<h2 id="计算交点法">§6.2 计算交点法</h2>
<p>该方法通过记分板来计算玩家视线和方块的各个面的交点位置。最后判断这些方块是否满足我们的条件。我们省略与上一节重复的一些内容。</p>

<pre class="file">cpp:blocks/acacia_leaves/locate</pre>
<pre>
function <a href="#cpp/functions/locate/init">cpp:locate/init</a>
execute as @e[type=marker,distance=..10,tag=cpp_locate_block] at @s if block ~ ~ ~ acacia_leaves align xyz positioned ~0.5 ~ ~0.5 unless entity @e[type=armor_stand,tag=cpp_leaves,distance=..0.1] run tag @s add cpp_locate_block_position
execute unless entity @e[type=marker,distance=..6.1,tag=cpp_locate_block_position] run function <a href="#cpp/functions/locate/neighbor">cpp:locate/neighbor</a>
execute as @e[type=marker,distance=..10,tag=cpp_locate_block_neighbor] at @s if block ~ ~ ~ acacia_leaves align xyz positioned ~0.5 ~ ~0.5 unless entity @e[type=armor_stand,tag=cpp_leaves,distance=..0.1] run tag @s add cpp_locate_block_position
execute at @e[type=marker,distance=..7.1,tag=cpp_locate_block_position,sort=nearest,limit=1] align xyz positioned ~0.5 ~ ~0.5 run function <a href="#cpp/functions/blocks/acacia_leaves/put">cpp:blocks/acacia_leaves/put</a>
kill @e[type=marker,distance=..10,tag=cpp_locate_block]
</pre>
<p>我们判断玩家离原点的距离来区分三个距离区间，从而离原点更近的地方可以获得不超过 2/7100 的误差，而距离稍远处误差会有所增大。</p>
<pre class="file" id="cpp/functions/locate/init">cpp:locate/init</pre>
<pre>
execute anchored eyes run summon marker ^ ^ ^ {Tags:["cpp_locate_block"]}
execute anchored eyes run summon marker ^ ^ ^1 {Tags:["cpp_locate_block_front"]}
execute store result score #x cppValue run data get entity @e[type=marker,distance=..3,tag=cpp_locate_block,limit=1] Pos[0] 71
execute store result score #z cppValue run data get entity @e[type=marker,distance=..3,tag=cpp_locate_block,limit=1] Pos[2] 71
scoreboard players operation #tempx cppValue = #x cppValue
execute if score #x cppValue matches ..-1 run scoreboard players operation #tempx cppValue *= #-1 cppValue
scoreboard players operation #tempz cppValue = #z cppValue
execute if score #z cppValue matches ..-1 run scoreboard players operation #tempz cppValue *= #-1 cppValue
scoreboard players operation #tempx cppValue > #tempz cppValue
execute if score #tempx cppValue matches 213000001.. run function <a href="#cpp/functions/locate/init1">cpp:locate/init1</a>
execute if score #tempx cppValue matches 21300001..213000000 run function <a href="#cpp/functions/locate/init10">cpp:locate/init10</a>
execute if score #tempx cppValue matches ..21300000 run function <a href="#cpp/functions/locate/init100">cpp:locate/init100</a>
kill @e[type=marker,tag=cpp_locate_block_front]
</pre>

<p>进行计算的初始化。</p>
<pre class="file" id="cpp/functions/locate/init1">cpp:locate/init100</pre>
<pre>
execute store result score #x cppValue run data get entity @e[type=marker,distance=..3,tag=cpp_locate_block,limit=1] Pos[0] 7100
execute store result score #y cppValue run data get entity @e[type=marker,distance=..3,tag=cpp_locate_block,limit=1] Pos[1] 7100
execute store result score #z cppValue run data get entity @e[type=marker,distance=..3,tag=cpp_locate_block,limit=1] Pos[2] 7100
execute store result score #f cppValue run data get entity @e[type=marker,distance=..3,tag=cpp_locate_block_front,limit=1] Pos[0] 7100
execute store result score #g cppValue run data get entity @e[type=marker,distance=..3,tag=cpp_locate_block_front,limit=1] Pos[1] 7100
execute store result score #h cppValue run data get entity @e[type=marker,distance=..3,tag=cpp_locate_block_front,limit=1] Pos[2] 7100
scoreboard players operation #f cppValue -= #x cppValue
scoreboard players operation #g cppValue -= #y cppValue
scoreboard players operation #h cppValue -= #z cppValue
scoreboard players operation #sf cppValue = #f cppValue
scoreboard players operation #sg cppValue = #g cppValue
scoreboard players operation #sh cppValue = #h cppValue
execute if score #sf cppValue matches ..-1 run scoreboard players operation #x cppValue *= #-1 cppValue
execute if score #sg cppValue matches ..-1 run scoreboard players operation #y cppValue *= #-1 cppValue
execute if score #sh cppValue matches ..-1 run scoreboard players operation #z cppValue *= #-1 cppValue
execute if score #sf cppValue matches ..-1 run scoreboard players operation #f cppValue *= #-1 cppValue
execute if score #sg cppValue matches ..-1 run scoreboard players operation #g cppValue *= #-1 cppValue
execute if score #sh cppValue matches ..-1 run scoreboard players operation #h cppValue *= #-1 cppValue
function <a href="#cpp/functions/locate/loop100">cpp:locate/loop100</a>
</pre>

<p>递归计算视线上的每一个方块交点。</p>
<pre class="file" id="cpp/functions/locate/loop100">cpp:locate/loop100</pre>
<pre>
tag @e[type=marker,distance=..8,tag=cpp_locate_block,tag=cpp_temp] remove cpp_temp
scoreboard players operation #t1 cppValue = #x cppValue
scoreboard players operation #t1 cppValue *= #-1 cppValue
scoreboard players operation #t1 cppValue %= #7100 cppValue
execute if score #t1 cppValue matches 0..1 run scoreboard players add #t1 cppValue 7100
scoreboard players operation #t1 cppValue *= #7100 cppValue
scoreboard players operation #t1 cppValue /= #f cppValue
scoreboard players operation #t2 cppValue = #y cppValue
scoreboard players operation #t2 cppValue *= #-1 cppValue
scoreboard players operation #t2 cppValue %= #7100 cppValue
execute if score #t2 cppValue matches 0..1 run scoreboard players add #t2 cppValue 7100
scoreboard players operation #t2 cppValue *= #7100 cppValue
scoreboard players operation #t2 cppValue /= #g cppValue
scoreboard players operation #t3 cppValue = #z cppValue
scoreboard players operation #t3 cppValue *= #-1 cppValue
scoreboard players operation #t3 cppValue %= #7100 cppValue
execute if score #t3 cppValue matches 0..1 run scoreboard players add #t3 cppValue 7100
scoreboard players operation #t3 cppValue *= #7100 cppValue
scoreboard players operation #t3 cppValue /= #h cppValue
scoreboard players operation #t1 cppValue &lt; #t2 cppValue
scoreboard players operation #t1 cppValue &lt; #t3 cppValue
scoreboard players operation #s1 cppValue = #f cppValue
scoreboard players operation #s2 cppValue = #g cppValue
scoreboard players operation #s3 cppValue = #h cppValue
scoreboard players operation #s1 cppValue *= #t1 cppValue
scoreboard players operation #s2 cppValue *= #t1 cppValue
scoreboard players operation #s3 cppValue *= #t1 cppValue
scoreboard players operation #s1 cppValue /= #7100 cppValue
scoreboard players operation #s2 cppValue /= #7100 cppValue
scoreboard players operation #s3 cppValue /= #7100 cppValue
scoreboard players operation #x cppValue += #s1 cppValue
scoreboard players operation #y cppValue += #s2 cppValue
scoreboard players operation #z cppValue += #s3 cppValue
summon marker ~ ~ ~ {Tags:["cpp_locate_block","cpp_temp"]}
execute if score #sf cppValue matches 0.. store result entity @e[type=marker,distance=..6.5,tag=cpp_locate_block,tag=cpp_temp,limit=1] Pos[0] double 0.00014084507042254 run scoreboard players get #x cppValue
execute if score #sg cppValue matches 0.. store result entity @e[type=marker,distance=..6.5,tag=cpp_locate_block,tag=cpp_temp,limit=1] Pos[1] double 0.00014084507042254 run scoreboard players get #y cppValue
execute if score #sh cppValue matches 0.. store result entity @e[type=marker,distance=..6.5,tag=cpp_locate_block,tag=cpp_temp,limit=1] Pos[2] double 0.00014084507042254 run scoreboard players get #z cppValue
execute if score #sf cppValue matches ..-1 store result entity @e[type=marker,distance=..6.5,tag=cpp_locate_block,tag=cpp_temp,limit=1] Pos[0] double -0.00014084507042254 run scoreboard players get #x cppValue
execute if score #sg cppValue matches ..-1 store result entity @e[type=marker,distance=..6.5,tag=cpp_locate_block,tag=cpp_temp,limit=1] Pos[1] double -0.00014084507042254 run scoreboard players get #y cppValue
execute if score #sh cppValue matches ..-1 store result entity @e[type=marker,distance=..6.5,tag=cpp_locate_block,tag=cpp_temp,limit=1] Pos[2] double -0.00014084507042254 run scoreboard players get #z cppValue
execute at @e[type=marker,distance=..10,tag=cpp_locate_block,tag=cpp_temp] if entity @s[distance=..8] run function <a href="#cpp/functions/locate/loop100">cpp:locate/loop100</a>
</pre>

<p>当标记位置所有方块均不符合我们要求时，我们检测邻近6个位置。</p>
<pre class="file" id="cpp/functions/locate/neighbor">cpp:locate/neighbor</pre>
<pre>
execute at @e[type=marker,distance=..10,tag=cpp_locate_block] run function <a href="#cpp/functions/locate/neighbor_aec">cpp:locate/neighbor_aec</a>
kill @e[type=marker,distance=..10,tag=cpp_locate_block,tag=!cpp_locate_block_neighbor]
</pre>
<pre class="file" id="cpp/functions/locate/neighbor_aec">cpp:locate/neighbor_aec</pre>
<pre>
summon marker ~1 ~ ~ {Tags:["cpp_locate_block","cpp_locate_block_neighbor"]}
summon marker ~-1 ~ ~ {Tags:["cpp_locate_block","cpp_locate_block_neighbor"]}
summon marker ~ ~1 ~ {Tags:["cpp_locate_block","cpp_locate_block_neighbor"]}
summon marker ~ ~-1 ~ {Tags:["cpp_locate_block","cpp_locate_block_neighbor"]}
summon marker ~ ~ ~1 {Tags:["cpp_locate_block","cpp_locate_block_neighbor"]}
summon marker ~ ~ ~-1 {Tags:["cpp_locate_block","cpp_locate_block_neighbor"]}
</pre>

<p>尽管看上去比较长，但是递归的次数很少，命令数比视线追踪法还是要少很多。设置为71/710/7100倍是为了保证记分板的计算过程中不会超过记分板的上下限而溢出。</p>

<h2 id="命令方块替换法">§6.3 命令方块替换法</h2>
<p>为了避免视线追踪不够精确，以及为了避免放置于不完整方块侧面等情形而导致方块不在视线上，我们可以考虑使用特殊方块来识别玩家放置的方块。一种是使用生存不存在的方块，例如石化橡木台阶，一种是使用具有特定NBT的实体方块，例如带有特定CustomName的容器。检测完成后应该将方块替换或修改掉，以保证后续放置的方块仍然具有独一性。该方式在服务中需要启用命令方块方可。</p>
<pre class="file" id="cpp/loot_tables/crafting_machine">cpp/loot_tables/crafting_machine.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:petrified_oak_slab",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{id:\"cpp:crafting_machine\",CustomModelData:12970001}"
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<pre class="file" id="cpp/advancements/blocks/petrified_oak_slab">cpp:advancements/blocks/petrified_oak_slab.json</pre>
<pre>
{
  "criteria": {
    "petrified_oak_slab": {
      "trigger": "minecraft:placed_block",
      "conditions": {
        "item": {
          "items": ["minecraft:petrified_oak_slab"]
        }
      }
    }
  },
  "rewards": {
    "function": "<a href="#cpp/functions/blocks/petrified_oak_slab/reset">cpp:blocks/petrified_oak_slab/reset</a>"
  }
}
</pre>
<pre class="file" id="cpp/functions/blocks/petrified_oak_slab/reset">cpp:blocks/petrified_oak_slab/reset</pre>
<pre>
advancement revoke @s only <a href="#cpp/advancements/blocks/petrified_oak_slab">cpp:blocks/petrified_oak_slab</a>
fill ~-6 ~-6 ~-6 ~6 ~6 ~6 command_block{auto:1b,Command:"execute align xyz positioned ~0.5 ~ ~0.5 run function <a href="#cpp/functions/blocks/petrified_oak_slab/crafting_machine">cpp:blocks/petrified_oak_slab/crafting_machine</a>"} replace petrified_oak_slab
execute positioned ~ -6 ~ as @s[dy=12] run fill ~-6 0 ~-6 ~6 12 ~6 command_block{auto:1b,Command:"execute align xyz positioned ~0.5 ~ ~0.5 run function <a href="#cpp/functions/blocks/petrified_oak_slab/crafting_machine">cpp:blocks/petrified_oak_slab/crafting_machine</a>"} replace petrified_oak_slab
execute positioned ~ 249 ~ as @s[dy=12] run fill ~-6 243 ~-6 ~6 255 ~6 command_block{auto:1b,Command:"execute align xyz positioned ~0.5 ~ ~0.5 run function <a href="#cpp/functions/blocks/petrified_oak_slab/crafting_machine">cpp:blocks/petrified_oak_slab/crafting_machine</a>"} replace petrified_oak_slab
</pre>
<pre class="file" id="cpp/functions/blocks/petrified_oak_slab/crafting_machine">cpp:blocks/petrified_oak_slab/crafting_machine</pre>
<pre>
setblock ~ ~ ~ barrel{CustomName:'{"translate":"block.minecraft.petrified_oak_slab"}'}
summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Small:1b,Marker:1b,NoGravity:1b,DisabledSlots:7967,Tags:["cpp_blocks"]}
execute as @e[type=armor_stand,tag=cpp_blocks,distance=..0.1,limit=1] run function <a href="#cpp/functions/blocks/petrified_oak_slab/tag">cpp:blocks/petrified_oak_slab/tag</a>
</pre>

<p>该方法也可以不借助命令方块。将玩家附近的方块复制到一定高度后，将所有方块破坏之，然后特定掉落物的相对位置就是相应方块位置。不过需要注意可能会影响原有方块或掉落物。也可以使用实体标记，通过修改其 <code>Pos</code> 来遍历玩家附近位置，找到特定方块时执行对应操作即可，不过这至多需要执行1000多次函数，开销并不小。</p>

<h2 id="破坏事件">§6.4 破坏事件</h2>
<p class="ex">高频检测标记所在位置的方块是否发生变化。若不符合要求，则表示该方块已被破坏(或被活塞推动)，此时检测附近相应掉落物并修改之，然后US杀死标记。</p>
<pre class="file">cpp:tick</pre>
<pre>
execute as @e[type=armor_stand,tag=cpp_leaves] at @s unless block ~ ~ ~ acacia_leaves run function <a href="#cpp/functions/blocks/acacia_leaves/break">cpp:blocks/acacia_leaves/break</a>
</pre>
<pre class="file" id="cpp/functions/blocks/acacia_leaves/break">cpp:blocks/acacia_leaves/break</pre>
<pre>
<span class="comment"># 树叶</span>
execute as @e[type=item,sort=nearest,predicate=<a href="#cpp/predicates/item/dropped_acacia_leaves">cpp:item/dropped_acacia_leaves</a>,limit=1,distance=..3] unless data entity @s Item.tag.id run tag @s add cpp_block_drop
data modify entity @e[type=item,sort=nearest,tag=cpp_block_drop,limit=1,distance=..3] Item set from entity @s ArmorItems[3]
tag @e[type=item,distance=..3,tag=cpp_block_drop] remove cpp_block_drop
<span class="comment"># 树苗</span>
execute as @e[type=item,sort=nearest,predicate=<a href="#cpp/predicates/item/dropped_acacia_sapling">cpp:item/dropped_acacia_sapling</a>,limit=1,distance=..3] run tag @s add cpp_block_drop
execute as @s[tag=cpp_ore_leaves] at @e[type=item,sort=nearest,tag=cpp_block_drop,limit=1,distance=..3] run loot spawn ~ ~ ~ loot cpp:ore_sapling
execute as @s[tag=cpp_wool_leaves] at @e[type=item,sort=nearest,tag=cpp_block_drop,limit=1,distance=..3] run loot spawn ~ ~ ~ loot cpp:wool_sapling
execute as @s[tag=cpp_fruit_leaves] at @e[type=item,sort=nearest,tag=cpp_block_drop,limit=1,distance=..3] run loot spawn ~ ~ ~ loot cpp:fruit_sapling
execute as @s[tag=cpp_sakura_leaves] at @e[type=item,sort=nearest,tag=cpp_block_drop,limit=1,distance=..3] run loot spawn ~ ~ ~ loot cpp:sakura_sapling
kill @e[type=item,distance=..3,tag=cpp_block_drop]
kill @s
</pre>
<pre class="file" id="cpp/predicates/item/dropped_acacia_leaves">cpp/predicates/item/dropped_acacia_leaves.json</pre>
<pre>
{
  "condition": "minecraft:entity_properties",
  "entity": "this",
  "predicate": {
    "nbt": "{Age:0s,Item:{id:\"minecraft:acacia_leaves\",Count:1b}}"
  }
}</pre>
<pre class="file" id="cpp/predicates/item/dropped_acacia_sapling">cpp/predicates/item/dropped_acacia_sapling.json</pre>
<pre>
{
  "condition": "minecraft:alternative",
  "terms": [
    {
      "condition": "minecraft:entity_properties",
      "entity": "this",
      "predicate": {
        "nbt": "{Age:0s,Item:{id:\"minecraft:acacia_sapling\",Count:1b}}"
      }
    },
    {
      "condition": "minecraft:entity_properties",
      "entity": "this",
      "predicate": {
        "nbt": "{Age:1s,Item:{id:\"minecraft:acacia_sapling\",Count:1b}}"
      }
    }
  ]
}</pre>
<p>对于树苗我们需要添加 <code>Age:0s</code> (挖掘)和 <code>Age:1s</code> (自然腐烂)两种情形。</p>

<h2 id="模型设置">§6.5 模型设置</h2>
<p>使用如下的 <code>display</code> 来放缩物品在头部的大小，可以保证其与坐标轴基本对齐。</p>
<pre class="file" id="assets/cpp/models/material/moon_stone">assets/cpp/models/material/moon_stone.json</pre>
<pre>
{
  "parent": "block/cube_all",
  "display": {
    "head": {
      "rotation": [ 0, 0, 0 ],
      "translation": [ 0, -14.65, 0 ],
      "scale": [ 2.29, 2.29, 2.29 ]
    }
  },
  "textures": {
    "all": "cpp:material/moon_stone"
  }
}
</pre>

<h1 id="机器设计">§7 机器设计</h1>
<p>本节我们将通过一个较为复杂的机器的例子，来了解如何设计一个机器。</p>

<p>首先参考 <a href="#物品设计">§5 物品设计</a>和 <a href="#方块设计">§6 方块设计</a>将机器方块设计好，我们这里选择木桶，木桶的优点是打开时没有动画，且栏位数比较多。如果对透明度有要求，使用箱子也可以，但要注意箱子有打开动画，以及避免出现大箱子的问题。</p>

<pre class="file" id="cpp/loot_tables/all_in_one_machine">cpp/loot_tables/all_in_one_machine.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:barrel",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{display:{Name:'{\"translate\":\"item.mac.all_in_one_machine\"}'},id:\"cpp:all_in_one_machine\",CustomModelData:12970001}"
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<p>然后绘制 GUI。这个机器左侧包括三个按钮，分别表示温度、压强和输出方向。输出方向用于机器自动将输出栏物品输入到相应方向邻近的容器。</p>
<ul>
  <li>GUI 整体是左上槽位的一个物品放大一定倍数并平移之后得到的。</li>
  <li>按钮、进度条、能源条均为物品模型。我们将使用经验作为能源。</li>
  <li>其余背景位置以及输出槽均为完全透明物品的模型。</li>
</ul>
<figure>
  <img src="items/all_in_one_machine.png" alt="机器GUI" />
  <figcaption>图7.1 机器GUI</figcaption>
</figure>

<h2 id="GUI纹理模型">§7.1 GUI纹理模型</h2>
<p>物品的默认大小为 <code>16×16</code>，所以如果我们想要将其放大 <code>n</code> 倍，就需要绘制大小为 <code>16n×16n</code> 的纹理，以对齐边缘和像素。</p>

<p>该模型用于机器的GUI，我们将其大小放大了 <code>12</code> 倍，也就是 <code>192×192</code> 大小。所以我们需要绘制这个大小的整数倍的纹理。通过修改z轴高度可调整纹理的覆盖次序。</p>

<pre class="file" id="assets/cpp/models/machine/gui/template">assets/cpp/models/machine/gui/template.json</pre>
<pre>
{
  "elements": [
    {
      "from": [ -16, 0, 0 ],
      "to": [ 32, 16, 1 ],
      "faces": {
        "south": { "uv":[0,0,16,16],"texture": "#layer0"}
      }
    }
  ],
  "gui_light": "front",
  "display": {
    "gui": {
      "scale": [ 3.375, 3.375, 1 ],
      "translation": [ 72, -18, -80]
    },
    "ground": {
      "scale": [ 0, 0, 0 ]
    }
  }
}
</pre>
<pre class="file" id="assets/cpp/models/machine/gui/all_in_one_machine">assets/cpp/models/machine/gui/all_in_one_machine.json</pre>
<pre>
{
  "parent": "cpp:machine/gui/template",
  "textures": {
    "layer0": "cpp:machine/gui/all_in_one_machine"
  }
}
</pre>
<p>这个图片大小为 <code>162×54</code>，即木桶所有栏位的大小。当该物品放置在木桶的第一格栏位时，经过上述放缩和平移，该物品的纹理正好和木桶的物品栏对齐。</p>

<figure>
  <img src="items/all_in_one_machine_gui.png" style="width:324px;" alt="机器纹理" />
  <figcaption>图7.2 cpp/textures/machine/gui/all_in_one_machine.png</figcaption>
</figure>

<p>若想要绘制各边缘超过这个距离限制的，可以重新调整 <code>display.gui.translation</code> 来对齐。更多注意事项请参阅<a href="#模型">§3.6 模型</a>。</p>

<p>对于机器的按钮，为了保证我们点击时不会出现按钮乱跑的问题，我们可以在按钮的实际模型放置在点击处的右一格，但这并不能避免玩家点击右一格时按钮的闪烁问题。为简便起见，我们不采用该技巧。</p>
<pre class="file" id="assets/cpp/models/machine/option/temp">assets/cpp/models/machine/option/temp.json</pre>
<pre>
{
  "parent": "item/generated",
  "display": {
    "gui": {
      "translation": [ -18, 0, 1 ]
    },
    "ground": {
      "scale": [ 0, 0, 0 ]
    }
  }
}
</pre>
<pre class="file" id="assets/cpp/models/machine/option/high_pressure">assets/cpp/models/machine/option/high_pressure.json</pre>
<pre>
{
  "parent": "cpp:machine/option/temp",
  "textures": {
    "layer0": "cpp:machine/option/high_pressure"
  }
}
</pre>

<p>对于机器的能源条，我们使用三个模型来实现。这样的优点是如果当我们需要更换纹理时，只需要改变能源条的模型和纹理即可。</p>
<p>第一个是能源条，能源条为动态纹理，位于最底层</p>
<pre class="file" id="assets/cpp/models/machine/xp/xp">assets/cpp/models/machine/xp/xp.json</pre>
<pre>
{
  "parent": "item/generated",
  "textures": {
    "layer0": "cpp:machine/xp/xp"
  },
  "display": {
    "gui": {
      "scale": [ 3.125, 3.125, 1 ],
      "translation": [17, -17, -65]
    },
    "ground": {
      "scale": [ 0, 0, 0 ]
    }
  }
}
</pre>
<pre class="file" id="assets/cpp/textures/machine/xp/xp.png.mcmeta">assets/cpp/textures/machine/xp/xp.png.mcmeta</pre>
<pre>
{
  "animation": {
    "frametime": 2
  }
}
</pre>
<figure>
  <img src="items/xp.png" style="width:25px;" alt="能源条" />
  <figcaption>图8.3 assets/cpp/textures/machine/xp/xp.png</figcaption>
</figure>

<p>第二个是能源标尺框架，位于中间层。</p>
<pre class="file" id="assets/cpp/models/machine/xp/frame">assets/cpp/models/machine/xp/frame.json</pre>
<pre>
{
  "parent": "item/generated",
  "display": {
    "gui": {
      "scale": [ 1.125, 3.25, 0 ],
      "translation": [ 0, 19, -55]
    },
    "ground": {
      "scale": [ 0, 0, 0 ]
    }
    },
    "textures": {
        "layer0": "cpp:machine/xp/frame"
    }
}
</pre>
<figure>
  <img src="items/frame.png" style="width:72px;" alt="能源标尺框架" />
  <figcaption>图7.4 assets/cpp/models/machine/xp/frame.png</figcaption>
</figure>

<p>我们将能源条划分为<code>0~100</code>共101种情形，第三层是用于遮挡能源条的101个与背景色相同的纯色方块。通过设置方块的高度放缩比例和平移，我们可以组合出只显示部分能源条的效果。公式为 <code>scale[1]=0.03125×(100-n),translation[1]=1+0.25n</code>。</p>
<pre class="file" id="assets/cpp/models/machine/xp/88">assets/cpp/models/machine/xp/88.json</pre>
<pre>
{
  "parent": "cpp:machine/xp/temp",
  "display": {
    "gui": {
      "scale": [1, 0.375, 1],
      "translation": [0, 23, -60]
    }
  }
} 
</pre>
<pre class="file" id="assets/cpp/models/machine/xp/temp">assets/cpp/models/machine/xp/temp.json</pre>
<pre>
{
  "parent": "item/generated",
  "textures": {
      "layer0": "cpp:pt"
  },
  "display": {
      "ground": {
          "scale": [ 0, 0, 0 ]
      }
  }
}
</pre>

<p>如果你擅长绘制UI的话，可以制作出很精美的UI。例如<a href="https://www.youtube.com/watch?v=bv_wYNs5L6M">该视频</a>中的GUI均是采用物品纹理绘制的。</p>

<figure>
  <img src="items/机器GUI示例1.png" style="width:50%;" alt="机器GUI示例1" />
  <figcaption>图7.5 机器GUI示例1</figcaption>
</figure>

<figure>
  <img src="items/机器GUI示例2.png" style="width:50%;" alt="机器GUI示例2" />
  <figcaption>图7.6 机器GUI示例2</figcaption>
</figure>

<h2 id="GUI背景处理">§7.2 GUI背景处理</h2>
<p>我们为所有的机器背景物品添加 <code>exClear:1b</code>。我们假设这个物品都是 <code>firework_star</code>。如果是多种物品的话，我们可以将这些物品 <code>id</code> 添加至一个物品标签内来统一清理。</p>

<p>清理玩家背包和地面的相应物品。</p>
<pre class="file">cpp:tick</pre>
<pre>
clear @a firework_star{exClear:1b}
kill @e[type=item,nbt={Item:{tag:{exClear:1b}}}]
execute as @e[type=armor_stand,tag=machine_machine] at @s run function <a href="#cpp/functions/blocks/machine">cpp:blocks/machine</a>
</pre>

<p>禁用机器下方的漏斗矿车内，并将下方漏斗的冷却时间高频设置为2。</p>
<pre class="file" id="cpp/functions/blocks/machine">cpp:blocks/machine</pre>
<pre>
execute positioned ~-1 ~-2 ~-1 as @e[type=hopper_minecart,dx=2,dy=2,dz=2] run data modify entity @s Enabled set value 0b
execute if block ~ ~-1 ~ hopper run data modify block ~ ~-1 ~ TransferCooldown set value 2
</pre>

<h2 id="GUI命令">§7.3 GUI命令</h2>
<p>我们需要对机器高频固定住其GUI，同时对于玩家误放入的物品进行弹出处理，并操作机器选项和经验条。</p>

<pre class="file" id="cpp/functions/all_in_one_machine/tick">cpp:all_in_one_machine/tick</pre>
<pre>
function <a href="#cpp/functions/misc/xp">cpp:misc/xp</a>
execute unless predicate <a href="#cpp/predicates/all_in_one_machine/gui">cpp:all_in_one_machine/gui</a> run function <a href="#cpp/functions/all_in_one_machine/gui">cpp:all_in_one_machine/gui</a>
execute unless data block ~ ~ ~ Items[{Slot:21b}] run item block ~ ~ ~ container.21 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.output_slot"}'},CustomModelData:12970000}
execute unless data block ~ ~ ~ Items[{Slot:22b}] run item block ~ ~ ~ container.22 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.output_slot"}'},CustomModelData:12970000}
execute as @s[tag=!cpp_machine_work] run function <a href="#cpp/functions/all_in_one_machine/idle">cpp:all_in_one_machine/idle</a>
tag @s remove cpp_machine_work
execute unless predicate <a href="#cpp/predicates/power/strong">cpp:power/strong</a> as @s[scores={cppExp=1..}] if block ~ ~ ~ barrel{Items:[{Slot:3b},{Slot:4b},{Slot:21b,tag:{cppClear:1b}},{Slot:22b,tag:{cppClear:1b}}]} run function <a href="#cpp/functions/all_in_one_machine/type">cpp:all_in_one_machine/type</a>
execute unless data block ~ ~ ~ Items[{Slot:21b,tag:{cppClear:1b}}] run function <a href="#cpp/functions/dist/dist21">cpp:dist/dist21</a>
execute unless data block ~ ~ ~ Items[{Slot:22b,tag:{cppClear:1b}}] run function <a href="#cpp/functions/dist/dist22">cpp:dist/dist22</a>
</pre>
<pre class="file" id="cpp/predicates/all_in_one_machine/gui">cpp/predicates/all_in_one_machine/gui.json</pre>
<pre>
{
  "condition": "minecraft:location_check",
  "predicate": {
    "block": {
      "nbt": "{Items:[{Slot:0b,tag:{cppClear:1b}},{Slot:1b,tag:{cppClear:1b}},{Slot:2b,tag:{cppClear:1b}},{Slot:5b,tag:{cppClear:1b}},{Slot:6b,tag:{cppClear:1b}},{Slot:8b,tag:{cppClear:1b}},{Slot:9b,tag:{cppClear:1b}},{Slot:10b,tag:{cppClear:1b}},{Slot:11b,tag:{cppClear:1b}},{Slot:12b,tag:{cppClear:1b}},{Slot:13b,tag:{cppClear:1b}},{Slot:14b,tag:{cppClear:1b}},{Slot:15b,tag:{cppClear:1b}},{Slot:16b,tag:{cppClear:1b}},{Slot:17b,tag:{cppClear:1b}},{Slot:18b,tag:{cppClear:1b}},{Slot:19b,tag:{cppClear:1b}},{Slot:20b,tag:{cppClear:1b}},{Slot:23b,tag:{cppClear:1b}},{Slot:24b,tag:{cppClear:1b}},{Slot:25b,tag:{cppClear:1b}},{Slot:26b,tag:{cppClear:1b}}]}"
    }
  }
}
</pre>

<p>处理经验：当经验瓶栏放入了附魔之瓶时，进行清理和增加经验的操作，并刷新显示能源条。我们用战利品表来动态设置能源数值显示。</p>
<pre class="file" id="cpp/functions/misc/xp">cpp:misc/xp</pre>
<pre>
execute as @s[scores={cppExp=0..991}] if data block ~ ~ ~ Items[{Slot:7b,id:"minecraft:experience_bottle"}] run function <a href="#cpp/functions/misc/xp_add">cpp:misc/xp_add</a>
</pre>
<pre class="file" id="cpp/functions/misc/xp_add">cpp:misc/xp_add</pre>
<pre>
item block ~ ~ ~ container.7 modify <a href="#cpp/item_modifiers/minus">cpp:minus</a>
scoreboard players add @s cppExp 9
function <a href="#cpp/functions/misc/xp_show">cpp:misc/xp_show</a>
</pre>
<pre class="file" id="cpp/functions/misc/xp_show">cpp:misc/xp_show</pre>
<pre>
loot replace block ~ ~ ~ container.8 1 loot cpp:misc/xp_show1
loot replace block ~ ~ ~ container.17 1 loot cpp:misc/xp_show1
loot replace block ~ ~ ~ container.26 1 loot cpp:misc/xp_show2
scoreboard players operation #t cppValue = @s cppExp
execute unless score #t cppValue matches 0..1000 run scoreboard players set #t cppValue 1000
execute store result block ~ ~ ~ Items[{Slot:17b}].tag.CustomModelData int 0.1 run scoreboard players add #t cppValue 129720000
</pre>
<pre class="file" id="cpp/loot_tables/xp_show1">cpp/loot_tables/xp_show1.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cppClear:1b,display:{Name:'{\"italic\":false,\"translate\":\"item.cpp.xp_bar\"}'},CustomModelData:12972102}"
            },
            {
              "function": "minecraft:set_lore",
              "lore": [
                [{"score":{"name":"@s","objective":"cppExp"},"color":"green","italic":false},{"text":"/1000"}]
              ],
              "entity": "this",
              "replace": true
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<pre class="file" id="cpp/loot_tables/xp_show2">cpp/loot_tables/xp_show2.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cppClear:1b,display:{Name:'{\"italic\":false,\"translate\":\"item.cpp.xp_bar\"}'},CustomModelData:12972101}"
            },
            {
              "function": "minecraft:set_lore",
              "lore": [
                [{"score":{"name":"@s","objective":"cppExp"},"color":"green","italic":false},{"text":"/1000"}]
              ],
              "entity": "this",
              "replace": true
            }
          ]
        }
      ]
    }
  ]
}
</pre>

<p>对于玩家误放入背景的物品，我们使用 <a href="#修改玩家背包">§10.2 修改玩家背包</a>中的潜影盒战利品表来将物品输出到容器中。</p>
<pre class="file" id="cpp/functions/all_in_one_machine/gui">cpp:all_in_one_machine/gui</pre>
<pre>
<span class="comment"># 动态弹出非法放入的物品</span>
setblock ~ 255 ~ shulker_box
data modify block ~ 255 ~ Items set from block ~ ~ ~ Items
data remove block ~ 255 ~ Items[{tag:{cppClear:1b}}]
data remove block ~ 255 ~ Items[{Slot:3b}]
data remove block ~ 255 ~ Items[{Slot:4b}]
data remove block ~ 255 ~ Items[{Slot:7b}]
data remove block ~ 255 ~ Items[{Slot:21b}]
data remove block ~ 255 ~ Items[{Slot:22b}]
loot give @p mine ~ 255 ~ tnt{drop_content:1b}
setblock ~ 255 ~ air
<span class="comment"># 选项</span>
execute unless data block ~ ~ ~ Items[{Slot:1b}] run function <a href="#cpp/functions/all_in_one_machine/option/pressure">cpp:all_in_one_machine/option/pressure</a>
execute unless data block ~ ~ ~ Items[{Slot:10b}] run function <a href="#cpp/functions/all_in_one_machine/option/temperature">cpp:all_in_one_machine/option/temperature</a>
execute unless data block ~ ~ ~ Items[{Slot:19b}] run function <a href="#cpp/functions/misc/output">cpp:misc/output</a>
<span class="comment"># 重置背景</span>
item block ~ ~ ~ container.0 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.all_in_one_machine"}'},CustomModelData:12971003}
loot replace block ~ ~ ~ container.1 1 loot cpp:all_in_one_machine/pressure
item block ~ ~ ~ container.2 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.all_in_one_machine"}'},CustomModelData:12970000}
item block ~ ~ ~ container.5 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.all_in_one_machine"}'},CustomModelData:12970000}
item block ~ ~ ~ container.6 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.all_in_one_machine"}'},CustomModelData:12970000}
item block ~ ~ ~ container.9 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.all_in_one_machine"}'},CustomModelData:12970000}
loot replace block ~ ~ ~ container.10 1 loot cpp:all_in_one_machine/temperature
item block ~ ~ ~ container.11 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.all_in_one_machine"}'},CustomModelData:12970000}
item block ~ ~ ~ container.12 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.process_shower"}'},CustomModelData:12971080}
item block ~ ~ ~ container.13 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.process_shower"}'},CustomModelData:12970000}
item block ~ ~ ~ container.14 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.all_in_one_machine"}'},CustomModelData:12970000}
item block ~ ~ ~ container.15 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.all_in_one_machine"}'},CustomModelData:12970000}
item block ~ ~ ~ container.16 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.all_in_one_machine"}'},CustomModelData:12970000}
item block ~ ~ ~ container.18 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.all_in_one_machine"}'},CustomModelData:12970000}
loot replace block ~ ~ ~ container.19 1 loot cpp:misc/switch
item block ~ ~ ~ container.20 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.all_in_one_machine"}'},CustomModelData:12970000}
item block ~ ~ ~ container.23 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.all_in_one_machine"}'},CustomModelData:12970000}
item block ~ ~ ~ container.24 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.all_in_one_machine"}'},CustomModelData:12970000}
item block ~ ~ ~ container.25 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.xp_remove"}'},CustomModelData:12970000}
function <a href="#cpp/functions/misc/xp_show">cpp:misc/xp_show</a>
</pre>

<p>当玩家点击按钮时，调整选项。</p>
<pre class="file" id="cpp/functions/all_in_one_machine/option/pressure">cpp:all_in_one_machine/option/pressure</pre>
<pre>
scoreboard players add @s cppAiomPres 1
scoreboard players set @s[scores={cppAiomPres=3..}] cppAiomPres 0
scoreboard players set @s[tag=!cpp_high_pressure,scores={cppAiomPres=2}] cppAiomPres 0
scoreboard players set @s[tag=!cpp_low_pressure,scores={cppAiomPres=0}] cppAiomPres 1
</pre>
<pre class="file" id="cpp/loot_tables/all_in_one_machine/pressure">cpp/loot_tables/all_in_one_machine/pressure.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cppClear:1b,display:{Lore:['{\"translate\":\"lore.cpp.switch\"}']}}"
            },
            {
              "conditions": [
                {
                  "condition": "minecraft:entity_scores",
                  "entity": "this",
                  "scores": {
                    "cppAiomPres": 0
                  }
                }
              ],
              "function": "minecraft:set_nbt",
              "tag": "{display:{Name:'{\"italic\":false,\"translate\":\"item.cpp.low_pressure\"}'},CustomModelData:12971051}"
            },
            {
              "conditions": [
                {
                  "condition": "minecraft:entity_scores",
                  "entity": "this",
                  "scores": {
                    "cppAiomPres": 1
                  }
                }
              ],
              "function": "minecraft:set_nbt",
              "tag": "{display:{Name:'{\"italic\":false,\"translate\":\"item.cpp.normal_pressure\"}'},CustomModelData:12971052}"
            },
            {
              "conditions": [
                {
                  "condition": "minecraft:entity_scores",
                  "entity": "this",
                  "scores": {
                    "cppAiomPres": 2
                  }
                }
              ],
              "function": "minecraft:set_nbt",
              "tag": "{display:{Name:'{\"italic\":false,\"translate\":\"item.cpp.high_pressure\"}'},CustomModelData:12971053}"
            }
          ]
        }
      ]
    }
  ]
}
</pre>

<p>机器空闲时进行一些重置操作。</p>
<pre class="file" id="cpp/functions/all_in_one_machine/idle">cpp:all_in_one_machine/idle</pre>
<pre>
data modify block ~ ~ ~ Items[{Slot:12b}].tag.CustomModelData set value 12971080
data modify entity @s ArmorItems[3].tag.CustomModelData set value 12970001
scoreboard players set @s cppTick 0
</pre>

<p>然后判断机器处是否有红石信号强充能，断言 <code>cpp:power/strong</code> 见 <a href="#红石信号">§10.3 红石信号</a>。当机器未被强充能、有经验值、有输入物、输出栏空闲时，进入配方判断。这里我们根据要求的温度压强来分类。</p>
<pre class="file" id="cpp/functions/all_in_one_machine/type">cpp:all_in_one_machine/type</pre>
<pre>
function #cpp:all_in_one_machine
execute as @s[scores={cppAiomTemp=0,cppAiomPres=0}] run function <a href="#cpp/functions/all_in_one_machine/recipes/ll/ll_1_1">cpp:all_in_one_machine/recipes/ll/ll_1_1</a>
execute as @s[scores={cppAiomTemp=0,cppAiomPres=1}] run function <a href="#cpp/functions/all_in_one_machine/recipes/ln/ln_1_1">cpp:all_in_one_machine/recipes/ln/ln_1_1</a>
execute as @s[scores={cppAiomTemp=0,cppAiomPres=2}] run function <a href="#cpp/functions/all_in_one_machine/recipes/lh">cpp:all_in_one_machine/recipes/lh</a>
execute as @s[scores={cppAiomTemp=1,cppAiomPres=0}] run function <a href="#cpp/functions/all_in_one_machine/recipes/nl">cpp:all_in_one_machine/recipes/nl</a>
execute as @s[scores={cppAiomTemp=1,cppAiomPres=1}] run function <a href="#cpp/functions/all_in_one_machine/recipes/nn">cpp:all_in_one_machine/recipes/nn</a>
execute as @s[scores={cppAiomTemp=1,cppAiomPres=2}] run function <a href="#cpp/functions/all_in_one_machine/recipes/nh">cpp:all_in_one_machine/recipes/nh</a>
execute as @s[scores={cppAiomTemp=2,cppAiomPres=0}] run function <a href="#cpp/functions/all_in_one_machine/recipes/hl/hl_4_10">cpp:all_in_one_machine/recipes/hl/hl_4_10</a>
execute as @s[scores={cppAiomTemp=2,cppAiomPres=1}] run function <a href="#cpp/functions/all_in_one_machine/recipes/hn">cpp:all_in_one_machine/recipes/hn</a>
execute as @s[scores={cppAiomTemp=2,cppAiomPres=2}] run function <a href="#cpp/functions/all_in_one_machine/recipes/hh">cpp:all_in_one_machine/recipes/hh</a>
execute unless data block ~ ~ ~ Items[{Slot:21b,tag:{cppClear:1b}}] run function <a href="#cpp/functions/all_in_one_machine/clear">cpp:all_in_one_machine/clear</a>
execute as @s[scores={cppTick=1..}] run function <a href="#cpp/functions/all_in_one_machine/option/process">cpp:all_in_one_machine/option/process</a>
data modify entity @s[tag=cpp_machine_work] ArmorItems[3].tag.CustomModelData set value 12970101
</pre>

<p>显示进度条。这里我们预先计算了半个进度条的刻数，然后加到当前刻数，计算后取整，这样得到进度条更加准确。</p>
<pre class="file" id="cpp/functions/all_in_one_machine/option/process">cpp:all_in_one_machine/option/process</pre>
<pre>
scoreboard players set #t cppValue 16
scoreboard players operation #t cppValue *= @s cppTick
scoreboard players operation #t cppValue += #process_pre cppValue
scoreboard players operation #t cppValue /= $allInOneMachinePeriod cppConfig
execute store result block ~ ~ ~ Items[{Slot:12b}].tag.CustomModelData int 1 run scoreboard players add #t cppValue 12971080
</pre>

<p>最后我们将输出栏的物品输入到邻近的容器内。</p>
<pre class="file" id="cpp/functions/dist/dist21">cpp:dist/dist21</pre>
<pre>
data modify storage cpp:dist Item set from block ~ ~ ~ Items[{Slot:21b}]
tag @s remove cpp_dist_success
function <a href="#cpp/functions/dist/machine">cpp:dist/machine</a>
execute as @s[tag=cpp_dist_success] run item block ~ ~ ~ container.21 replace firework_star{cppClear:1b,display:{Name:'{"italic":false,"translate":"item.cpp.output_slot"}'},CustomModelData:12970000}
</pre>

<h2 id="物品输出">§7.4 物品输出</h2>
<p>上一节我们调用了一个函数用于输出物品，我们来看一下它的算法。</p>

<p>根据机器的输出方向调整位置。</p>
<pre class="file" id="cpp/functions/dist/machine">cpp:dist/machine</pre>
<pre>
execute as @s[scores={cppMacOut=1}] positioned ~1 ~ ~ run function <a href="#cpp/functions/dist/pos">cpp:dist/pos</a>
execute as @s[scores={cppMacOut=2}] positioned ~ ~ ~1 run function <a href="#cpp/functions/dist/pos">cpp:dist/pos</a>
execute as @s[scores={cppMacOut=3}] positioned ~-1 ~ ~ run function <a href="#cpp/functions/dist/pos">cpp:dist/pos</a>
execute as @s[scores={cppMacOut=4}] positioned ~ ~ ~-1 run function <a href="#cpp/functions/dist/pos">cpp:dist/pos</a>
execute as @s[scores={cppMacOut=5}] positioned ~ ~-1 ~ run function <a href="#cpp/functions/dist/pos">cpp:dist/pos</a>
execute as @s[scores={cppMacOut=6}] positioned ~ ~1 ~ run function <a href="#cpp/functions/dist/pos">cpp:dist/pos</a>
</pre>

<p>我们把大箱子添加至方块标签中。如果是大箱子的右半个，将其修改为左半个位置。</p>
<pre class="file" id="cpp/function/dist/pos">cpp/function/dist/pos</pre>
<pre>
execute if block ~ ~ ~ #cpp:chests[type=left,facing=east] positioned ~ ~ ~1 run function <a href="#cpp/functions/dist/pos2">cpp:dist/pos2</a>
execute if block ~ ~ ~ #cpp:chests[type=left,facing=west] positioned ~ ~ ~-1 run function <a href="#cpp/functions/dist/pos2">cpp:dist/pos2</a>
execute if block ~ ~ ~ #cpp:chests[type=left,facing=south] positioned ~-1 ~ ~ run function <a href="#cpp/functions/dist/pos2">cpp:dist/pos2</a>
execute if block ~ ~ ~ #cpp:chests[type=left,facing=north] positioned ~1 ~ ~ run function <a href="#cpp/functions/dist/pos2">cpp:dist/pos2</a>
execute unless block ~ ~ ~ #cpp:chests[type=left] run function <a href="#cpp/functions/dist/pos2  ">cpp:dist/pos2  </a>
</pre>

<p>我们通过插入包含一个不可堆叠的物品的战利品表，并比较有物品的栏位数有没有发生改变来判断其是否有空栏位。如果当前位置没有空栏位且为大箱子，调整输出的位置。</p>
<pre class="file" id="cpp/function/dist/pos2">cpp/function/dist/pos2</pre>
<pre>
clone ~ ~ ~ ~ ~ ~ ~ 255 ~
execute store result score #t cppValue run data get block ~ 255 ~ Items
loot insert ~ 255 ~ loot cpp:misc/iron_axe
execute store result score #s cppValue run data get block ~ 255 ~ Items
setblock ~ 255 ~ air
execute if score #t cppValue = #s cppValue run tag @s add cpp_container_full
execute as @s[tag=!cpp_container_full] run function <a href="#cpp/functions/dist/dist">cpp:dist/dist</a>
execute as @s[tag=!cpp_dist_success,tag=cpp_container_full] if block ~ ~ ~ #cpp:chests[type=right,facing=east] positioned ~ ~ ~-1 run function <a href="#cpp/functions/dist/double">cpp:dist/double</a>
execute as @s[tag=!cpp_dist_success,tag=cpp_container_full] if block ~ ~ ~ #cpp:chests[type=right,facing=west] positioned ~ ~ ~1 run function <a href="#cpp/functions/dist/double">cpp:dist/double</a>
execute as @s[tag=!cpp_dist_success,tag=cpp_container_full] if block ~ ~ ~ #cpp:chests[type=right,facing=south] positioned ~1 ~ ~ run function <a href="#cpp/functions/dist/double">cpp:dist/double</a>
execute as @s[tag=!cpp_dist_success,tag=cpp_container_full] if block ~ ~ ~ #cpp:chests[type=right,facing=north] positioned ~-1 ~ ~ run function <a href="#cpp/functions/dist/double">cpp:dist/double</a>
tag @s remove cpp_container_full
</pre>
<pre class="file" id="cpp/functions/dist/double">cpp:dist/double</pre>
<pre>
clone ~ ~ ~ ~ ~ ~ ~ 255 ~
execute store result score #t cppValue run data get block ~ 255 ~ Items
loot insert ~ 255 ~ loot cpp:misc/iron_axe
execute store result score #s cppValue run data get block ~ 255 ~ Items
setblock ~ 255 ~ air
execute unless score #t cppValue = #s cppValue run function <a href="#cpp/functions/dist/dist">cpp:dist/dist</a>
</pre>

<p>最后使用 <a href="#修改玩家背包">§10.2 修改玩家背包</a>中的潜影盒战利品表来将物品输出到容器中。</p>
<pre class="file" id="cpp/functions/dist/dist">cpp:dist/dist</pre>
<pre>
tag @s add cpp_dist_success
setblock ~ 255 ~ shulker_box
data remove storage cpp:dist Item.Slot
data modify block ~ 255 ~ Items[{Slot:0b}] merge from storage cpp:dist Item
loot insert ~ ~ ~ mine ~ 255 ~ tnt{drop_content:1b}
setblock ~ 255 ~ air  
</pre>

<h2 id="配方处理">§7.5 配方处理</h2>
<p>我们使用断言判断机器的物品是否满足相应配方的条件，然后进入计时。计时完成后进行产物生成，产物的生成通过使用战利品表判断当前位置的NBT得到。</p>
<pre class="file" id="cpp/functions/all_in_one_machine/recipes/nn">cpp:all_in_one_machine/recipes/nn</pre>
<pre>
execute as @s[scores={cppExp=2..}] if predicate <a href="#cpp/predicates/all_in_one_machine/nn_2_2">cpp:all_in_one_machine/nn_2_2</a> run function <a href="#cpp/functions/all_in_one_machine/recipes/nn/nn_2_2">cpp:all_in_one_machine/recipes/nn/nn_2_2</a>
</pre>
<pre class="file" id="cpp/predicates/all_in_one_machine/nn_2_2">cpp/predicates/all_in_one_machine/nn_2_2.json</pre>
<pre>
{
  "condition": "minecraft:alternative",
  "terms": [
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{tag:{id:\"cpp:fertilizer\"}},{id:\"minecraft:wheat_seeds\"}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{tag:{id:\"cpp:fertilizer\"}},{id:\"minecraft:beetroot_seeds\"}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{tag:{id:\"cpp:fertilizer\"}},{id:\"minecraft:carrot\"}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{tag:{id:\"cpp:fertilizer\"}},{id:\"minecraft:potato\"}]}"
        }
      }
    }
  ]
}
</pre>

<p>这里需要注意一种极端情形，如果同一条件下的函数中，有多条判断原材料的命令，而且这些为无序配方（即不检测具体栏位），而且所有产物和原材料中，有部分物品可以进行其它合成，那么我们需要在这些判断中添加 <code>as @s[tag=!mac_machine_work]</code> 或者 <code>if block ~ ~ ~ barrel{Items:[{Slot:16b,tag:{exClear:1b}}]}</code> 来对机器是否已工作进行判断，否则有可能导致前一个配方的产物正常被后一个配方识别到，而导致配方出现混乱。</p>

<pre class="file" id="cpp/functions/all_in_one_machine/recipes/nn/nn_2_2">cpp:all_in_one_machine/recipes/nn/nn_2_2</pre>
<pre>
tag @s add cpp_machine_work
scoreboard players add @s cppTick 30
execute if score @s cppTick >= $allInOneMachinePeriod cppConfig run function <a href="#cpp/functions/all_in_one_machine/recipes/nn/nn_2_2_done">cpp:all_in_one_machine/recipes/nn/nn_2_2_done</a>
</pre>
<pre class="file" id="cpp/functions/all_in_one_machine/recipes/nn/nn_2_2_done">cpp:all_in_one_machine/recipes/nn/nn_2_2_done</pre>
<pre>
scoreboard players remove @s cppExp 2
loot replace block ~ ~ ~ container.21 2 loot <a href="#cpp/loot_tables/all_in_one_machine/nn_2_2">cpp:all_in_one_machine/nn_2_2</a>
</pre>
<pre class="file" id="cpp/loot_tables/all_in_one_machine/nn_2_2">cpp/loot_tables/all_in_one_machine/nn_2_2.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:alternatives",
          "children": [
            {
              "conditions": [
                {
                  "condition": "minecraft:location_check",
                  "predicate": {
                    "block": {
                      "nbt": "{Items:[{tag:{id:\"cpp:fertilizer\"}},{id:\"minecraft:wheat_seeds\"}]}"
                    }
                  }
                }
              ],
              "type": "minecraft:loot_table",
              "name": "cpp:all_in_one_machine/items/wheats"
            },
            {
              "conditions": [
                {
                  "condition": "minecraft:location_check",
                  "predicate": {
                    "block": {
                      "nbt": "{Items:[{tag:{id:\"cpp:fertilizer\"}},{id:\"minecraft:beetroot_seeds\"}]}"
                    }
                  }
                }
              ],
              "type": "minecraft:loot_table",
              "name": "cpp:all_in_one_machine/items/beetroots"
            },
            {
              "conditions": [
                {
                  "condition": "minecraft:location_check",
                  "predicate": {
                    "block": {
                      "nbt": "{Items:[{tag:{id:\"cpp:fertilizer\"}},{id:\"minecraft:carrot\"}]}"
                    }
                  }
                }
              ],
              "type": "minecraft:item",
              "name": "minecraft:carrot",
              "functions":[
                {
                  "function": "minecraft:set_count",
                  "count": 6
                }
              ]
            },
            {
              "conditions": [
                {
                  "condition": "minecraft:location_check",
                  "predicate": {
                    "block": {
                      "nbt": "{Items:[{tag:{id:\"cpp:fertilizer\"}},{id:\"minecraft:potato\"}]}"
                    }
                  }
                }
              ],
              "type": "minecraft:item",
              "name": "minecraft:potato",
              "functions":[
                {
                  "function": "minecraft:set_count",
                  "count": 6
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}
</pre>

<p>这样，输出槽就产生了物品，然后通过上一节中相关函数命令，进入清理环节。如果你的配方并不是100%有产物的，则需要在计时完成中添加机器完成工作的标签，然后根据标签来判断是否进入清理环节。</p>
<pre class="file" id="cpp/functions/all_in_one_machine/clear">cpp:all_in_one_machine/clear</pre>
<pre>
scoreboard players set @s cppTick 0
item block ~ ~ ~ container.4 modify <a href="#cpp/item_modifiers/minus">cpp:minus</a>
item block ~ ~ ~ container.3 modify <a href="#cpp/item_modifiers/minus">cpp:minus</a>
function <a href="#cpp/functions/misc/xp_show">cpp:misc/xp_show</a>
</pre>

<p>对于特殊的物品，例如药水、水桶等，我们可能希望能够返还玻璃瓶、桶等，此时我们需要进行额外的预处理。</p>
<pre>
execute if data block ~ ~ ~ Items[{id:"minecraft:water_bucket"}] run function <a href="#cpp/functions/crafting_machine/craft/clear/water_bucket">cpp:crafting_machine/craft/clear/water_bucket</a>
</pre>

<p>我们通过计算单个堆叠和多个堆叠的栏位数，来得到该有多少玻璃瓶进入输出的容器。如果容器满了，计算进入玩家背包的数量，处理应当留下的数量。尽管水桶等物品不可堆叠，但我们仍保留考虑其它模组使其可堆叠的情形。</p>
<pre class="file" id="cpp/functions/crafting_machine/craft/clear/water_bucket">cpp:crafting_machine/craft/clear/water_bucket</pre>
<pre>
data modify storage cpp:_ Items set from block ~ ~ ~ Items
execute store result score #t1 cppValue run data remove storage cpp:_ Items[{id:"minecraft:water_bucket",Count:1b}]
execute store result score #t2 cppValue run data remove storage cpp:_ Items[{id:"minecraft:water_bucket"}]
data modify storage cpp:dist Item set value {id:"minecraft:bucket",Count:1b}
execute store result storage cpp:dist Item.Count byte 1 run scoreboard players operation #t1 cppValue += #t2 cppValue
tag @s remove cpp_dist_success
function <a href="#cpp/functions/dist/machine">cpp:dist/machine</a>
execute as @s[tag=!cpp_dist_success] run data remove block ~ ~ ~ Items[{id:"minecraft:water_bucket",Count:1b}].tag
execute as @s[tag=!cpp_dist_success] if data block ~ ~ ~ Items[{id:"minecraft:water_bucket",Count:1b}] run data modify block ~ ~ ~ Items[{id:"minecraft:water_bucket",Count:1b}] merge value {id:"minecraft:bucket",Count:2b}
execute as @s[tag=!cpp_dist_success] run loot give @p loot cpp:crafting_machine/items/bucket
</pre>

<h2 id="插件">§7.6 插件</h2>
<p>前面我们提到机器有多种模式，包括温度和压强的调整。我们可以要求玩家使用特定物品插件shift右击机器来安装。插件原型为胡萝卜钓竿。</p>
<p>我们省略副手情形的处理。</p>

<pre class="file">cpp:tick</pre>
<pre>
execute as @a[scores={cppUseCSt=1..}] run function <a href="#cpp/functions/use_cst/type">cpp:use_cst/type</a>
</pre>
<pre class="file" id="cpp/functions/use_cst/type">cpp:use_cst/type</pre>
<pre>
scoreboard players reset @s cppUseCSt
execute as @s[predicate=<a href="#cpp/predicates/mainhand/carrot_on_a_stick">cpp:mainhand/carrot_on_a_stick</a>] run function <a href="#cpp/functions/use_cst/mainhand">cpp:use_cst/mainhand</a>
execute as @s[predicate=!<a href="#cpp/predicates/mainhand/carrot_on_a_stick">cpp:mainhand/carrot_on_a_stick</a>] run function <a href="#cpp/functions/use_cst/offhand">cpp:use_cst/offhand</a>
</pre>
<pre class="file" id="cpp/functions/use_cst/mainhand">cpp:use_cst/mainhand</pre>
<pre>
execute as @s[predicate=<a href="#cpp/predicates/mainhand/machine_plugin">cpp:mainhand/machine_plugin</a>] at @s anchored eyes run function <a href="#cpp/functions/all_in_one_machine/plugin/ray">cpp:all_in_one_machine/plugin/ray</a>
</pre>
<pre class="file" id="cpp/functions/all_in_one_machine/ray">cpp:all_in_one_machine/ray</pre>
<pre>
function <a href="#cpp/functions/locate/init">cpp:locate/init</a>
execute as @e[type=marker,distance=..10,tag=cpp_locate_block] at @s if block ~ ~ ~ barrel align xyz positioned ~0.5 ~ ~0.5 if entity @e[type=armor_stand,distance=..0.5,tag=cpp_all_in_one_machine] run tag @s add cpp_locate_block_position
execute at @e[type=marker,distance=..6.1,tag=cpp_locate_block_position,sort=nearest,limit=1] align xyz positioned ~0.5 ~ ~0.5 run function <a href="#cpp/functions/all_in_one_machine/plugin/type">cpp:all_in_one_machine/plugin/type</a>
kill @e[type=marker,distance=..10,tag=cpp_locate_block]
</pre>
<pre class="file" id="cpp/functions/all_in_one_machine/plugin/type">cpp:all_in_one_machine/plugin/type</pre>
<pre>
execute as @s[predicate=!<a href="#cpp/predicates/mainhand/carrot_on_a_stick">cpp:mainhand/carrot_on_a_stick</a>] run function <a href="#cpp/functions/all_in_one_machine/plugin/off">cpp:all_in_one_machine/plugin/off</a>
execute as @s[predicate=<a href="#cpp/predicates/mainhand/carrot_on_a_stick">cpp:mainhand/carrot_on_a_stick</a>] run function <a href="#cpp/functions/all_in_one_machine/plugin/main">cpp:all_in_one_machine/plugin/main</a>
</pre>
<pre class="file" id="cpp/functions/all_in_one_machine/plugin/main">cpp:all_in_one_machine/plugin/main</pre>
<pre>
execute as @s[predicate=<a href="#cpp/predicates/mainhand/high_pressure_plugin">cpp:mainhand/high_pressure_plugin</a>] if entity @e[type=armor_stand,tag=cpp_all_in_one_machine,distance=..0.5,limit=1] if entity @e[type=armor_stand,tag=cpp_all_in_one_machine,distance=..0.5,limit=1,tag=!cpp_high_pressure] run function <a href="#cpp/functions/all_in_one_machine/plugin/hp">cpp:all_in_one_machine/plugin/hp</a>
execute as @s[predicate=<a href="#cpp/predicates/mainhand/low_pressure_plugin">cpp:mainhand/low_pressure_plugin</a>] if entity @e[type=armor_stand,tag=cpp_all_in_one_machine,distance=..0.5,limit=1] if entity @e[type=armor_stand,tag=cpp_all_in_one_machine,distance=..0.5,limit=1,tag=!cpp_low_pressure] run function <a href="#cpp/functions/all_in_one_machine/plugin/lp">cpp:all_in_one_machine/plugin/lp</a>
execute as @s[predicate=<a href="#cpp/predicates/mainhand/high_temperature_plugin">cpp:mainhand/high_temperature_plugin</a>] if entity @e[type=armor_stand,tag=cpp_all_in_one_machine,distance=..0.5,limit=1] if entity @e[type=armor_stand,tag=cpp_all_in_one_machine,distance=..0.5,limit=1,tag=!cpp_high_temperature] run function <a href="#cpp/functions/all_in_one_machine/plugin/ht">cpp:all_in_one_machine/plugin/ht</a>
execute as @s[predicate=<a href="#cpp/predicates/mainhand/low_temperature_plugin">cpp:mainhand/low_temperature_plugin</a>] if entity @e[type=armor_stand,tag=cpp_all_in_one_machine,distance=..0.5,limit=1] if entity @e[type=armor_stand,tag=cpp_all_in_one_machine,distance=..0.5,limit=1,tag=!cpp_low_temperature] run function <a href="#cpp/functions/all_in_one_machine/plugin/lt">cpp:all_in_one_machine/plugin/lt</a>
</pre>
<pre class="file" id="cpp/functions/all_in_one_machine/plugin/hp">cpp:all_in_one_machine/plugin/hp</pre>
<pre>
tellraw @s [{"translate":"info.cpp.high_pressure_plugin"}]
tag @e[type=armor_stand,tag=cpp_all_in_one_machine,distance=..0.5,limit=1,tag=!cpp_high_pressure] add cpp_high_pressure
function <a href="#cpp/functions/all_in_one_machine/plugin/clear">cpp:all_in_one_machine/plugin/clear</a>
</pre>
<pre class="file" id="cpp/functions/all_in_one_machine/plugin/clear">cpp:all_in_one_machine/plugin/clear</pre>
<pre>
item entity @s[gamemode=!creative,predicate=!<a href="#cpp/predicates/mainhand/carrot_on_a_stick">cpp:mainhand/carrot_on_a_stick</a>] weapon.offhand replace air
item entity @s[gamemode=!creative,predicate=<a href="#cpp/predicates/mainhand/carrot_on_a_stick">cpp:mainhand/carrot_on_a_stick</a>] weapon.mainhand replace air  
</pre>

<p>我们也可以使用 <a href="#方块交互">§10.5 方块交互</a>的方式来安装插件。</p>


<h2 id="容器扩展">§7.7 容器扩展</h2>
<p>在 <a href="#物品输出">§7.4 物品输出</a>中，方块标签 <code>#cpp:chests</code> 记录了各种大箱子。如果添加更多可支持的容器，我们只需添加它们至该方块标签即可。</p>

<pre class="file" id="cpp/tags/blocks/chests">cpp/tags/blocks/chests.json</pre>
<pre>
{
  "replace": false,
  "values": [
    "minecraft:chest",
    "minecraft:trapped_chest",
    { "id": "stonechest:chest_andesite", "required": false},
    { "id": "stonechest:chest_cobblestone", "required": false},
    { "id": "stonechest:chest_diorite", "required": false},
    { "id": "stonechest:chest_granite", "required": false},
    { "id": "stonechest:chest_stone", "required": false},
    { "id": "quark:spruce_chest", "required": false},
    { "id": "quark:birch_chest", "required": false},
    { "id": "quark:jungle_chest", "required": false},
    { "id": "quark:acacia_chest", "required": false},
    { "id": "quark:dark_oak_chest", "required": false},
    { "id": "quark:oak_chest", "required": false},
    { "id": "quark:bamboo_chest", "required": false},
    { "id": "quark:driftwood_chest", "required": false},
    { "id": "quark:poise_chest", "required": false},
    { "id": "quark:willow_chest", "required": false},
    { "id": "quark:wisteria_chest", "required": false},
    { "id": "quark:nether_brick_chest", "required": false},
    { "id": "quark:purpur_chest", "required": false},
    { "id": "quark:prismarine_chest", "required": false},
    { "id": "quark:mushroom_chest", "required": false},
    { "id": "quark:crimson_chest", "required": false},
    { "id": "quark:warped_chest", "required": false},
    { "id": "quark:wisteria_chest", "required": false},
    { "id": "quark:wisteria_chest", "required": false},
    { "id": "quark:wisteria_chest", "required": false}
  ]
}
</pre>

<h2 id="接口">§7.8 接口</h2>
<p>函数 <code>cpp:all_in_one_machine/type</code> 中包含一条命令 <code>function #cpp:all_in_one_machine</code>。我们也创建了相应的函数标签。然后其他开发者便可向该函数标签写入内容来达到扩展或修改内容的目的，这也在 <a href="#前置与附属">§4.3 前置与附属</a>中提及。例如</p>

<pre class="file" id="foo:all_in_one_machine/type">foo:all_in_one_machine/type</pre>
<pre>
execute as @s[scores={cppTemperature=0,cppPressure=0}] run function foo:all_in_one_machine/recipes/bar
</pre>
<p>然后类似创建后续的断言、战利品表、函数。</p>

<h2 id="管道">§7.9 管道</h2>
<p>科技类模组人们需要添加管道来传输电力、流体、物品等。物品管道是类似的，我们将物品的信息存储在管道上并传输即可，最终将其输入到容器中。常见的几种做法有：</p>

<h3 id="无线传输">§7.9.1 无线传输</h3>
<p>优点是简洁易操作，判断输出电力的机器附近是否有需要输入电力的机器并计算即可。</p>

<pre class="file">cpp:tick</pre>
<pre>
execute as @e[type=armor_stand,tag=machine_machine,tag=cpp_power_source,scores={cppPower=1..}] at @s if entity @e[type=armor_stand,tag=machine_machine,tag=cpp_power_target,distance=..16] run function <a href="#cpp/functions/machine/power/translate">cpp:machine/power/translate</a>
</pre>
<pre class="file" id="cpp/functions/machine/power/translate">cpp:machine/power/translate</pre>
<pre>
tag @s add cpp_power_out
scoreboard players operation #t0 cppPower = @e[type=armor_stand,tag=machine_machine,tag=cpp_power_source,scores={cppPower=1..},distance=..1,limit=1] cppPower
execute as @e[type=armor_stand,tag=machine_machine,tag=cpp_power_target] if score @s cppPower &lt; @s cppPowerMax run function <a href="#cpp/functions/machine/power/translate1">cpp:machine/power/translate1</a>
scoreboard players operation @e[type=armor_stand,tag=machine_machine,tag=cpp_power_source,scores={cppPower=1..},distance=..1,limit=1] cppPower -= #t0 cppPower
tag @s remove cpp_power_out
</pre>
<pre class="file" id="cpp/functions/machine/power/translate1">cpp:machine/power/translate1</pre>
<pre>
scoreboard players operation #t cppPower = @s cppPowerMax
scoreboard players operation #t cppPower -= @s cppPower
execute if score #t cppPower &gt; #t0 cppPower run scoreboard players operation #t cppPower = #t0 cppPower
scoreboard players operation @s cppPower += #t cppPower
scoreboard players operation #t0 cppPower -= #t cppPower
</pre>

<p>我们也可以在传输中添加类似投射物的特效来提高视觉效果。</p>

<h3 id="管道式">§7.9.2 管道式</h3>
<p>优点是具有传统科技模组的风格，缺点是每个管道都是一个实体，管道多的时候会较为卡顿。若不用实体仅用原版特定方块来表示导线，则限制颇多。</p>
<p>涌流式：能量从高处向周围比它低的管道/机器处流动，来最终实现能量传输。管道内会留有缓存。实现和无线传输类似，只是范围限定在1米内。</p>
<p>遍历式：从能量源出发，遇到过的管道做标记一直向下，如果遇到终点就回溯到分叉点，一直循环直到返回源头。</p>
<p>具体实现方式省略。</p>

<h3 id="激光式">§7.9.3 激光式</h3>
<p>为了降低管道式的管道数量，我们可以将管道替换为可以一次传输多格的激光式管道。这里我们使用展示框来表示，计算其与前方方块的距离并调整外观（长度）。</p>

<pre class="file">cpp:tick</pre>
<pre>
execute as @e[type=item_frame,tag=cpp_wire] at @s run function <a href="#cpp/functions/wire/face">cpp:wire/face</a>
execute as @e[type=armor_stand,tag=cpp_power_out,scores={cppPower=1..}] at @s run function <a href="#cpp/functions/power/face">cpp:power/face</a>
</pre>
<pre class="file" id="cpp/functions/wire/face">cpp:wire/face</pre>
<pre>
scoreboard players set @s cppValue 7500000
execute as @s[nbt={Facing:0b}] align xyz positioned ~0.5 ~-1 ~0.5 run function <a href="#cpp/functions/wire/down">cpp:wire/down</a>
execute as @s[nbt={Facing:1b}] align xyz positioned ~0.5 ~1 ~0.5 run function <a href="#cpp/functions/wire/up">cpp:wire/up</a>
execute as @s[nbt={Facing:2b}] align xyz positioned ~0.5 ~ ~-0.5 run function <a href="#cpp/functions/wire/north">cpp:wire/north</a>
execute as @s[nbt={Facing:3b}] align xyz positioned ~0.5 ~ ~1.5 run function <a href="#cpp/functions/wire/south">cpp:wire/south</a>
execute as @s[nbt={Facing:4b}] align xyz positioned ~-0.5 ~ ~0.5 run function <a href="#cpp/functions/wire/west">cpp:wire/west</a>
execute as @s[nbt={Facing:5b}] align xyz positioned ~1.5 ~ ~0.5 run function <a href="#cpp/functions/wire/east">cpp:wire/east</a>
execute store result entity @s Item.tag.CustomModelData int 1 run scoreboard players get @s cppValue
</pre>
<pre class="file" id="cpp/functions/wire/east">cpp:wire/east</pre>
<pre>
scoreboard players add @s cppValue 1
execute if block ~ ~ ~ #cpp:fluid positioned ~1 ~ ~ run function <a href="#cpp/functions/wire/east">cpp:wire/east</a>
</pre>
<p>同样我们递归向前来获得接收能量的方块。</p>

<pre class="file" id="cpp/functions/power/face">cpp:power/face</pre>
<pre>
execute positioned ~0.5 ~0.5 ~ if entity @e[tag=cpp_wire,distance=..0.1] align xyz positioned ~1.5 ~ ~0.5 run function <a href="#cpp/functions/power/east">cpp:power/east</a>
execute positioned ~-0.5 ~0.5 ~ if entity @e[tag=cpp_wire,distance=..0.1] align xyz positioned ~-1.5 ~ ~0.5 run function <a href="#cpp/functions/power/west">cpp:power/west</a>
execute positioned ~ ~0.5 ~0.5 if entity @e[tag=cpp_wire,distance=..0.1] align xyz positioned ~0.5 ~ ~1.5 run function <a href="#cpp/functions/power/south">cpp:power/south</a>
execute positioned ~ ~0.5 ~-0.5 if entity @e[tag=cpp_wire,distance=..0.1] align xyz positioned ~0.5 ~ ~-1.5 run function <a href="#cpp/functions/power/north">cpp:power/north</a>
execute positioned ~ ~1 ~ if entity @e[tag=cpp_wire,distance=..0.1] align xyz positioned ~0.5 ~2 ~0.5 run function <a href="#cpp/functions/power/up">cpp:power/up</a>
execute if entity @e[tag=cpp_wire,distance=..0.1] align xyz positioned ~0.5 ~-2 ~0.5 run function <a href="#cpp/functions/power/down">cpp:power/down</a>
</pre>
<pre class="file" id="cpp/functions/power/east">cpp:power/east</pre>
<pre>
execute if entity @s[distance=..16] if entity @e[tag=cpp_power_in,distance=..0.1] entity @e[tag=cpp_power_in,distance=..0.1,limit=1,scores={cppPower=..9999}] if score @e[tag=cpp_power_in,distance=..0.1,limit=1] cppPower &lt; @e[tag=cpp_power_in,distance=..0.1,limit=1] cppPowerLimit run function <a href="#cpp/functions/power/in">cpp:power/in</a>
execute if entity @s[distance=..16] unless entity @e[tag=cpp_power_in,distance=..0.1] positioned ~1 ~ ~ run function <a href="#cpp/functions/power/east">cpp:power/east</a>
</pre>
<pre class="file" id="cpp/functions/power/in">cpp:power/in</pre>
<pre>
scoreboard players remove @s cppPower 1
scoreboard players add @e[tag=cpp_power_in,distance=..0.1,limit=1] cppPower 1
</pre>

<h3 id="载体式">§7.9.4 载体式</h3>
<p>我们使用一个可移动的实体来传输能量，这个实体受方块控制。</p>

<pre class="file" id="cpp/functions/golem/tick">cpp:golem/tick</pre>
<pre>
data merge entity @s {PortalCooldown:900}
execute if block ~ ~ ~ #cpp:golem_east run scoreboard players set @s cppGolemFace 0
execute if block ~ ~ ~ #cpp:golem_south run scoreboard players set @s cppGolemFace 1
execute if block ~ ~ ~ #cpp:golem_west run scoreboard players set @s cppGolemFace 2
execute if block ~ ~ ~ #cpp:golem_north run scoreboard players set @s cppGolemFace 3
execute if block ~ ~ ~ #cpp:golem_up run scoreboard players set @s cppGolemFace 4
execute if block ~ ~ ~ #cpp:golem_down run scoreboard players set @s cppGolemFace 5
execute as @s[scores={cppGolemFace=0}] run tp @s ~1 ~0 ~0 270 0
execute as @s[scores={cppGolemFace=1}] run tp @s ~0 ~0 ~1 0 0
execute as @s[scores={cppGolemFace=2}] run tp @s ~-1 ~0 ~0 90 0
execute as @s[scores={cppGolemFace=3}] run tp @s ~0 ~0 ~-1 180 0
execute as @s[scores={cppGolemFace=4}] run tp @s ~0 ~1 ~0 0 90
execute as @s[scores={cppGolemFace=5}] run tp @s ~0 ~-1 ~0 0 -90
execute as @s[scores={cppPower=1..}] if entity @e[type=armor_stand,tag=machine_machine,tag=cpp_power_in] run function <a href="#cpp/functions/power/translate">cpp:power/translate</a>
</pre>
<p>然后和其它传输方式一样，计算传输值即可。</p>

<h3 id="管道设计">§7.9.5 管道设计</h3>
<p>管道模型通常是不完整方块，我们可以使用屏障方块来作为管道的本体方块，使用扳手(胡萝卜钓竿)来右键拆解。</p>
<p>管道需要高频判断是否与周边方块连接，以调整其自身显示。</p>
<pre class="file" id="cpp/functions/pipe/tick">cpp:pipe/tick</pre>
<pre>
scoreboard players set @s cppModel 12970000
execute positioned ~1 ~ ~ if entity @e[type=armor_stand,tag=cpp_pipe,distance=..0.2] run scoreboard players add @s cppModel 1
execute positioned ~-1 ~ ~ if entity @e[type=armor_stand,tag=cpp_pipe,distance=..0.2] run scoreboard players add @s cppModel 2
execute positioned ~ ~ ~1 if entity @e[type=armor_stand,tag=cpp_pipe,distance=..0.2] run scoreboard players add @s cppModel 4
execute positioned ~ ~ ~-1 if entity @e[type=armor_stand,tag=cpp_pipe,distance=..0.2] run scoreboard players add @s cppModel 8
execute positioned ~ ~1 ~ if entity @e[type=armor_stand,tag=cpp_pipe,distance=..0.2] run scoreboard players add @s cppModel 16
execute positioned ~ ~-1 ~ if entity @e[type=armor_stand,tag=cpp_pipe,distance=..0.2] run scoreboard players add @s cppModel 32
execute store result entity @s ArmorItems[3].tag.CustomModelData int 1 run scoreboard players get @s cppModel
</pre>

<h1 id="NBT合成与烧炼">§8 NBT合成与烧炼</h1>
<h2 id="地板合成">§8.1 地板合成</h2>
<p>将物品扔在地面进行合成，是模组配方数量少时采用的一种便捷做法。优点是无需设计 GUI。</p>

<p class="ex">将磁铁（<code>id:"cpp:magnet"</code>）和4个钻石合成为充能指南针（<code>id:"cpp:powered_magnet"</code>）。</p>

<pre class="file">cpp:tick</pre>
<pre>
execute as @e[type=item,nbt={Item:{tag:{id:"cpp:magnet"}}}] at @s if entity @e[type=item,distance=..1,nbt={Item:{id:"minecraft:diamond",Count:4b}}] run function <a href="#cpp/functions/powered_magnet">cpp:powered_magnet</a>
</pre>
<pre class="file" id="cpp/functions/powered_magnet">cpp:powered_magnet</pre>
<pre>
kill @e[type=item,limit=1,distance=..1,nbt={Item:{id:"minecraft:diamond",Count:4b}}]
kill @s
summon item ~ ~ ~ {Item:{id:"minecraft:compass",Count:1b,tag:{id:"cpp:powered_magnet"}}}
</pre>

<h2 id="实体背包合成">§8.2 实体背包合成</h2>
<p>利用玩家的背包、末影箱、箱子矿车、驴等生物的背包用于合成，也是一种较为便捷的方式，不受方块的限制。</p>

<p>由于玩家的NBT难以修改，玩家背包和末影箱并不便于合成处理，而且一般只能用于有序合成。其它情形可以通过不指定 <code>Slot</code> 来实现无序合成。</p>

<p>当合成配方较多时，我们应当考虑分类以降低每刻命令数。常见的做法是先按配方的原材料种类数、或者合成的形状分类。</p>

<p class="ex">利用玩家背包的右方3×3区域进行合成。</p>

<pre class="file">cpp:tick</pre>
<pre>
scoreboard players set @a cppCraftSlot 0
scoreboard players add @a[nbt={Inventory:[{Slot:15b}]}] cppCraftSlot 1
scoreboard players add @a[nbt={Inventory:[{Slot:16b}]}] cppCraftSlot 1
scoreboard players add @a[nbt={Inventory:[{Slot:17b}]}] cppCraftSlot 1
scoreboard players add @a[nbt={Inventory:[{Slot:24b}]}] cppCraftSlot 1
scoreboard players add @a[nbt={Inventory:[{Slot:25b}]}] cppCraftSlot 1
scoreboard players add @a[nbt={Inventory:[{Slot:26b}]}] cppCraftSlot 1
scoreboard players add @a[nbt={Inventory:[{Slot:33b}]}] cppCraftSlot 1
scoreboard players add @a[nbt={Inventory:[{Slot:34b}]}] cppCraftSlot 1
scoreboard players add @a[nbt={Inventory:[{Slot:35b}]}] cppCraftSlot 1
execute as @a[scores={cppCraftSlot=1..}] run function <a href="#cpp/functions/craft">cpp:craft</a>
</pre>
<pre class="file" id="cpp/functions/craft">cpp:craft</pre>
<pre>
execute if predicate <a href="#cpp/predicate/craft/items">cpp:craft/items</a> run tag @s add cpp_craft
execute if predicate <a href="#cpp/predicate/craft/items">cpp:craft/items</a> run loot replace entity @s inventory.16 1 loot cpp:craft/items
item entity @s[tag=cpp_craft] inventory.6 replace air
item entity @s[tag=cpp_craft] inventory.7 replace air
item entity @s[tag=cpp_craft] inventory.8 replace air
item entity @s[tag=cpp_craft] inventory.15 replace air
item entity @s[tag=cpp_craft] inventory.17 replace air
item entity @s[tag=cpp_craft] inventory.24 replace air
item entity @s[tag=cpp_craft] inventory.25 replace air
item entity @s[tag=cpp_craft] inventory.26 replace air
tag @s remove cpp_craft
</pre>
<pre class="file" id="cpp/predicate/craft/items">cpp/predicates/craft/items</pre>
<pre>
{
  "condition": "minecraft:alternative",
  "terms": [
    {
      "condition": "minecraft:reference",
      "name": "cpp:craft/items1"
    },
    {
      "condition": "minecraft:reference",
      "name": "cpp:craft/items2"
    },
    {
      "condition": "minecraft:reference",
      "name": "cpp:craft/items3"
    },
    {
      "condition": "minecraft:reference",
      "name": "cpp:craft/items4"
    },
    {
      "condition": "minecraft:reference",
      "name": "cpp:craft/items5"
    },
    {
      "condition": "minecraft:reference",
      "name": "cpp:craft/items6"
    },
    {
      "condition": "minecraft:reference",
      "name": "cpp:craft/items7"
    },
    {
      "condition": "minecraft:reference",
      "name": "cpp:craft/items8"
    },
    {
      "condition": "minecraft:reference",
      "name": "cpp:craft/items9"
    }
  ]
}
</pre>
<pre class="file" id="cpp/predicate/craft/items5">cpp/predicates/craft/items5</pre>
<pre>
[
  {
    "condition": "minecraft:entity_scores",
    "entity": "this",
    "scores": {
      "cppCraftSlot": 5
    }
  },
  {
    "condition": "minecraft:alternative",
    "terms": [
      {
        "_comment": "酸水",
        "condition": "minecraft:location_check",
        "predicate": {
          "block": {
            "nbt": "{Items:[{Slot:6b,Count:1b,id:\"minecraft:sugar\"},{Slot:7b,Count:1b,id:\"minecraft:rotten_flesh\"},{Slot:8b,Count:1b,id:\"minecraft:glistering_melon_slice\"},{Slot:15b,Count:1b,id:\"minecraft:gunpowder\"},{Slot:16b,Count:1b,id:\"minecraft:potion\",tag:{Potion:\"minecraft:water\"}}]}"
          }
        }
      }
    ]
  }
]
</pre>
<pre class="file" id="cpp/loot_tables/craft/items">cpp/loot_tables/craft/items</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:alternatives",
          "children": [
            {
              "conditions": [
                {
                  "condition": "minecraft:entity_scores",
                  "entity": "this",
                  "scores": {
                    "cppCraftSlot": 1
                  }
                }
              ],
              "type": "minecraft:loot_table",
              "name": "cpp:craft/items1"
            },
            {
              "conditions": [
                {
                  "condition": "minecraft:entity_scores",
                  "entity": "this",
                  "scores": {
                    "cppCraftSlot": 2
                  }
                }
              ],
              "type": "minecraft:loot_table",
              "name": "cpp:craft/items2"
            },
            {
              "conditions": [
                {
                  "condition": "minecraft:entity_scores",
                  "entity": "this",
                  "scores": {
                    "cppCraftSlot": 3
                  }
                }
              ],
              "type": "minecraft:loot_table",
              "name": "cpp:craft/items3"
            },
            {
              "conditions": [
                {
                  "condition": "minecraft:entity_scores",
                  "entity": "this",
                  "scores": {
                    "cppCraftSlot": 4
                  }
                }
              ],
              "type": "minecraft:loot_table",
              "name": "cpp:craft/items4"
            },
            {
              "conditions": [
                {
                  "condition": "minecraft:entity_scores",
                  "entity": "this",
                  "scores": {
                    "cppCraftSlot": 5
                  }
                }
              ],
              "type": "minecraft:loot_table",
              "name": "cpp:craft/items5"
            },
            {
              "conditions": [
                {
                  "condition": "minecraft:entity_scores",
                  "entity": "this",
                  "scores": {
                    "cppCraftSlot": 6
                  }
                }
              ],
              "type": "minecraft:loot_table",
              "name": "cpp:craft/items6"
            },
            {
              "conditions": [
                {
                  "condition": "minecraft:entity_scores",
                  "entity": "this",
                  "scores": {
                    "cppCraftSlot": 7
                  }
                }
              ],
              "type": "minecraft:loot_table",
              "name": "cpp:craft/items7"
            },
            {
              "conditions": [
                {
                  "condition": "minecraft:entity_scores",
                  "entity": "this",
                  "scores": {
                    "cppCraftSlot": 8
                  }
                }
              ],
              "type": "minecraft:loot_table",
              "name": "cpp:craft/items8"
            },
            {
              "conditions": [
                {
                  "condition": "minecraft:entity_scores",
                  "entity": "this",
                  "scores": {
                    "cppCraftSlot": 9
                  }
                }
              ],
              "type": "minecraft:loot_table",
              "name": "cpp:craft/items9"
            }
          ]
        }
      ]
    }
  ]
}</pre>
<pre class="file" id="cpp/loot_tables/craft/items5">cpp/loot_tables/craft/items5</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:alternatives",
          "children": [
            {
              "_comment": "酸水",
              "conditions": [
                {
                  "condition": "minecraft:location_check",
                  "predicate": {
                    "block": {
                      "nbt": "{Items:[{Slot:6b,id:\"minecraft:sugar\"},{Slot:7b,id:\"minecraft:rotten_flesh\"},{Slot:8b,id:\"minecraft:glistering_melon_slice\"},{Slot:15b,id:\"minecraft:gunpowder\"},{Slot:16b,id:\"minecraft:potion\",tag:{Potion:\"minecraft:water\"}}]}"
                    }
                  }
                }
              ],
              "type": "minecraft:loot_table",
              "name": "cpp:acid"
            }
          ]
        }
      ]
    }
  ]
}
</pre>


<h2 id="容器合成">§8.3 容器合成</h2>
<p>使用投掷器、箱子、木桶等容器可以更为便捷地实现合成。我们可以直接使用容器，或者使用 <a href="#机器设计">§7 机器设计</a>的方法设计好自定义工作台的GUI。</p>
<p>输出方式我们可以选择输出到输出栏（木桶）、输出到自身（精准匹配+投掷器）、弹出。具体实现与 <a href="#机器设计">§7 机器设计</a>并无二致。</p>
<p>和上一节类似，我们仍然使用战利品表谓词来进行判断并使用战利品表得到产物。最后做清理。对于需要返还物品的处理，见 <a href="#配方处理">§7.5 配方处理</a>。</p>

<pre class="file" id="cpp/functions/crafting_machine/type">cpp:crafting_machine/type</pre>
<pre>
execute if predicate cpp:crafting_machine/items run loot replace block ~ ~ ~ container.16 1 loot cpp:crafting_machine/items
execute unless data block ~ ~ ~ Items[{Slot:16b,tag:{cppClear:1b}}] run function <a href="#cpp/functions/crafting_machine/clear/input">cpp:crafting_machine/clear/input</a>
</pre>
<pre class="file" id="cpp/functions/crafting_machine/clear/input">cpp:crafting_machine/clear/input</pre>
<pre>
execute if data block ~ ~ ~ Items[{id:"minecraft:water_bucket"}] run function cpp:crafting_machine/clear/water_bucket
execute if data block ~ ~ ~ Items[{id:"minecraft:lava_bucket"}] run function cpp:crafting_machine/clear/lava_bucket
execute if data block ~ ~ ~ Items[{id:"minecraft:milk_bucket"}] run function cpp:crafting_machine/clear/milk_bucket
execute if data block ~ ~ ~ Items[{id:"minecraft:cod_bucket"}] run function cpp:crafting_machine/clear/cod_bucket
execute if data block ~ ~ ~ Items[{id:"minecraft:salmon_bucket"}] run function cpp:crafting_machine/clear/salmon_bucket
execute if data block ~ ~ ~ Items[{id:"minecraft:tropical_fish_bucket"}] run function cpp:crafting_machine/clear/tropical_fish_bucket
execute if data block ~ ~ ~ Items[{id:"minecraft:pufferfish_bucket"}] run function cpp:crafting_machine/clear/pufferfish_bucket
execute if data block ~ ~ ~ Items[{id:"minecraft:axolot_bucket"}] run function cpp:crafting_machine/clear/axolot_bucket
execute if data block ~ ~ ~ Items[{id:"minecraft:potion"}] run function cpp:crafting_machine/clear/potion
execute if data block ~ ~ ~ Items[{id:"minecraft:honey_bottle"}] run function cpp:crafting_machine/clear/honey_bottle
item block ~ ~ ~ container.1 modify <a href="#cpp/item_modifiers/minus">cpp:minus</a>
item block ~ ~ ~ container.2 modify <a href="#cpp/item_modifiers/minus">cpp:minus</a>
item block ~ ~ ~ container.3 modify <a href="#cpp/item_modifiers/minus">cpp:minus</a>
item block ~ ~ ~ container.10 modify <a href="#cpp/item_modifiers/minus">cpp:minus</a>
item block ~ ~ ~ container.11 modify <a href="#cpp/item_modifiers/minus">cpp:minus</a>
item block ~ ~ ~ container.12 modify <a href="#cpp/item_modifiers/minus">cpp:minus</a>
item block ~ ~ ~ container.19 modify <a href="#cpp/item_modifiers/minus">cpp:minus</a>
item block ~ ~ ~ container.20 modify <a href="#cpp/item_modifiers/minus">cpp:minus</a>
item block ~ ~ ~ container.21 modify <a href="#cpp/item_modifiers/minus">cpp:minus</a>
</pre>

<h2 id="NBT烧炼">§8.4 NBT烧炼</h2>
<h2 id="替换产物法">§8.4.1 替换产物法</h2>
<p>放置熔炉、高炉、烟熏炉、营火的过程已省略。我们假设相应方块位置已有标签为 <code>cpp_furnace</code> 的盔甲架。</p>
<p class="ex">将蛋烧炼为战利品表物品 <code>cpp:egg_stew</code>。创建烧炼配方以激活烧炼蛋。</p>
<pre class="file" id="cpp/recipes/egg">cpp/recipes/egg.json</pre>
<pre>
{
  "type": "smelting",
  "ingredient": {
    "item": "minecraft:egg"
  },
  "result": "minecraft:mushroom_stew",
  "experience": 0.1,
  "cookingtime": 200
}
</pre>
<p class="noindent">然后在烧炼时间达到 <code>199s</code> 时，替换熔炉内的物品。</p>
<pre class="file">cpp:tick</pre>
<pre>
execute as @e[type=armor_stand,tag=cpp_furnace] at @s unless block ~ ~ ~ furnace run kill @s
execute as @e[type=armor_stand,tag=cpp_furnace] at @s if block ~ ~ ~ furnace{CookTime:199s} run function <a href="#cpp/functions/foods/cook/check">cpp:foods/cook/check</a>
</pre>
<pre class="file" id="cpp/functions/foods/cook/check">cpp:foods/cook/check</pre>
<pre>
execute if block ~ ~ ~ furnace{Items:[{Slot:0b,id:"minecraft:egg"}]} run function <a href="#cpp/functions/foods/cook/egg_stew">cpp:foods/cook/egg_stew</a>
</pre>
<pre class="file" id="cpp/functions/foods/cook/egg_stew">cpp:foods/cook/egg_stew</pre>
<pre>
loot replace entity @s weapon.mainhand 1 loot cpp:egg_stew
data modify block ~ ~ ~ Items[{Slot:2b}] set from entity @s HandItems[0]
item entity @s weapon.mainhand replace minecraft:air
execute store result block ~ ~ ~ Items[0].Count byte 0.999 run data get block ~ ~ ~ Items[0].Count
data merge block ~ ~ ~ {CookTime:0s}
</pre>
<p>注意这里不能通过战利品表将产物loot replace到熔炉的输出栏。</p>
<p>这种做法的局限性一是若要求待烧炼物含指定NBT，则必须添加该物品的的烧炼配方，这就导致即使没有相应的NBT也会烧炼，个人建议为原物品也添加合理的烧炼配方，或者烧炼配方的产物和待烧炼物相同，同时不奖励经验值；二是即使产物应当可堆叠也无法正常堆叠，这时需配合漏斗等设备传输方可持续烧炼。</p>

<table><thead><tr><th style="width:11em;">情形</th><th style="width:4em;">添加配方</th><th>注意事项</th></tr></thead><tbody>
<tr>
  <th>原版物品A->NBT物品B</th>
  <td>A->B</td>
  <td>在烧炼即将完成时生成产物。</td>
</tr>
<tr>
  <th rowspan="2">NBT物品A->原版物品B</th>
  <td>A->B</td>
  <td>同上一条。对于原版物品A，还需要清理产物或添加其它合适的烧炼效果。</td>
</tr>
<tr>
  <td>A->C</td>
  <td>同上一条。产物无法堆叠，需配合漏斗等设备传输方可持续烧炼。</td>
</tr>
<tr>
  <th rowspan="2">NBT物品A->NBT物品B</th>
  <td>A->B</td>
  <td>同上上条。若有其它烧炼配方可以得到原版物品B，则进行相应配方烧炼时的产物会直接变为NBT物品B，因此要排除这种情形。</td>
</tr>
<tr>
  <td>A->C</td>
  <td>同前两条。</td>
</tr>
</tbody></table>

<h2 id="记分板模拟">§8.4.2 记分板模拟</h2>
<p>另一种做法就是并不添加相应的烧炼配方，而是通过记分板计时来达到控制烧炼时间的目的。当物品进入熔炉后，判断其是否需要烧炼以及是否有燃料，然后判断输出栏是否为空或其产物，如果确实可以烧炼，那么临时存储输入输出栏物品至存储区，然后放入任意可烧炼物品以触发燃料的消耗和烧炼动画。下一刻再将存储区的物品返回熔炉。反复操作直到烧炼时间达到了烧炼该物品所需的时间，此时产出产物即可。(by chaoren019)</p>
<p>该方法在计算时会导致熔炉内物品闪烁一下(这可以通过自定义空白模型的铁矿石来解决)，更换不同燃烧值物品时，燃烧火焰条也会有所变化，这和通常烧炼配方有差异。</p>
<pre class="file" id="cpp/functions/furnace/tick">cpp:furnace/tick</pre>
<pre>
execute unless block ~ ~ ~ furnace run kill @s
execute as @s[tag=cpp_check_fuel] run function <a href="#cpp/functions/furnace/fuel_get">cpp:furnace/fuel_get</a>
execute unless block ~ ~ ~ furnace{Items:[{Slot:2b,Count:64b}]} unless block ~ ~ ~ furnace{Items:[{Slot:2b,Count:16b,id:"minecraft:ender_pearl"}]} if predicate <a href="#cpp/predicates/furnace/furnace">cpp:furnace/furnace</a> run function <a href="#cpp/functions/furnace/type">cpp:furnace/type</a>
</pre>
<p>当检测到燃料改变时，重新计算燃烧值。注意这需要在检测到改变的下一刻才能获得，因此该部分在最前面。</p>
<pre class="file" id="cpp/functions/furnace/fuel_get">cpp:furnace/fuel_get</pre>
<pre>
tag @s remove cpp_check_fuel
execute store result score @s cppValue run data get block ~ ~ ~ BurnTime
item block ~ ~ ~ container.0 replace air
data modify block ~ ~ ~ {} merge from entity @s HandItems[0].tag.storage
</pre>
<p>使用断言和战利品表来记录配方。这里断言需要分输出栏空和输出栏为相应产物两种情形。注意我们需要排除输出栏已满的情形，而这项判断又需要对部分不是64堆叠数的物品单独判断。</p>
<pre class="file" id="cpp/predicates/furnace/furnace">cpp/predicates/furnace/furnace.json</pre>
<pre>
{
  "condition": "minecraft:alternative",
  "terms": [
    {
      "condition": "minecraft:inverted",
      "term": {
        "condition": "minecraft:alternative",
        "terms": [
          {
            "condition": "minecraft:inverted",
            "term": {
              "condition": "minecraft:reference",
              "name": "<a href="#cpp/predicates/furnace/furnace1">cpp:furnace/furnace1</a>"
            }
          },
          {
            "condition": "minecraft:location_check",
            "predicate": {
              "block": {
                "nbt": "{Items:[{Slot:2b}]}"
              }
            }
          }
        ]
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{id:'cpp:clay_bucket'}},{Slot:2b,id:'minecraft:bucket'}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{id:'cpp:lycoris_radiata'}},{Slot:2b,id:'minecraft:red_dye'}]}"
        }
      }
    }
  ]
}
</pre>
<pre class="file" id="cpp/predicates/furnace/furnace1">cpp/predicates/furnace/furnace1.json</pre>
<pre>
{
  "condition": "minecraft:alternative",
  "terms": [
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{id:'cpp:clay_bucket'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{id:'cpp:lycoris_radiata'}}]}"
        }
      }
    }
  ]
}
</pre>
<pre class="file" id="cpp/functions/furnace/type">cpp:furnace/type</pre>
<pre>
<span class="comment"># 燃料改变</span>
execute if block ~ ~ ~ furnace{BurnTime:0s,Items:[{Slot:1b}]} run function <a href="#cpp/functions/furnace/fuel_change_check">cpp:furnace/fuel_change_check</a>
<span class="comment"># 消耗燃料</span>
execute as @s[tag=!cpp_check_fuel] if block ~ ~ ~ furnace{BurnTime:0s,Items:[{Slot:1b}]} run function <a href="#cpp/functions/furnace/fuel_use">cpp:furnace/fuel_use</a>
<span class="comment"># 进度</span>
execute unless block ~ ~ ~ furnace{BurnTime:0s} store result block ~ ~ ~ CookTime short 1 run scoreboard players add @s cppTick 1
execute if score @s cppTick matches 199.. run function <a href="#cpp/functions/furnace/done">cpp:furnace/done</a>
<span class="comment"># 停止</span>
execute if block ~ ~ ~ furnace{BurnTime:0s} run scoreboard players reset @s cppTick
<span class="comment"># 发光</span>
execute if predicate cpp:furnace/lit run function <a href="#cpp/functions/furnace/lit_true">cpp:furnace/lit_true</a>
execute if predicate cpp:furnace/unlit run function <a href="#cpp/functions/furnace/lit_false">cpp:furnace/lit_false</a>
</pre>
<p>在熔炉的盔甲架添加手持物来记录燃料的变化。</p>
<pre class="file" id="cpp/functions/furnace/fuel_change_check">cpp:furnace/fuel_change_check</pre>
<pre>
execute store result score #change cppValue run data modify entity @s HandItems[0].tag.id set from block ~ ~ ~ Items[{Slot:1b}].id
execute if score #change cppValue matches 1 run function <a href="#cpp/functions/furnace/fuel_change">cpp:furnace/fuel_change</a>
</pre>
<pre class="file" id="cpp/functions/furnace/fuel_change">cpp:furnace/fuel_change</pre>
<pre>
data modify entity @s HandItems[0].tag.storage set from block ~ ~ ~
item block ~ ~ ~ container.0 replace iron_ore
item block ~ ~ ~ container.2 replace air
tag @s add cpp_check_fuel
</pre>
<pre class="file" id="cpp/functions/furnace/fuel_use">cpp:furnace/fuel_use</pre>
<pre>
execute store result block ~ ~ ~ BurnTime short 1 run scoreboard players get @s cppValue
execute if data block ~ ~ ~ Items[{Slot:1b,id:"minecraft:lava_bucket",Count:1b}] run item block ~ ~ ~ container.1 replace bucket 2
item block ~ ~ ~ container.1 modify <a href="#cpp/item_modifiers/minus">cpp:minus</a>
</pre>
<p>烧炼完成时添加获取经验的配方记录，这里我们统一设定为每次0.15点，可以根据需要实现不同配方不同经验值。</p>
<pre class="file" id="cpp/functions/furnace/done">cpp:furnace/done</pre>
<pre>execute if data block ~ ~ ~ {Items:[{Slot:2b}]} run item block ~ ~ ~ container.2 modify <a href="#cpp/item_modifiers/plus">cpp:plus</a>
execute unless data block ~ ~ ~ {Items:[{Slot:2b}]} run function <a href="#cpp/functions/furnace/done_loot">cpp:smelt/furnace/done_loot</a>
item block ~ ~ ~ container.0 modify <a href="#cpp/item_modifiers/minus">cpp:minus</a>
scoreboard players reset @s cppTick
data modify block ~ ~ ~ CookTime set value 0s
execute store result score #t cppValue run data get block ~ ~ ~ RecipesUsed."minecraft:charcoal"
execute store result block ~ ~ ~ RecipesUsed."minecraft:charcoal" int 1 run scoreboard players add #t cppValue 1
</pre>
<p>烧炼完毕时，通过战利品表生成产物，注意不能直接 loot replace 进熔炉的输出槽。</p>
<pre class="file" id="cpp/functions/furnace/done_loot">cpp:furnace/done_loot</pre>
<pre>data remove block ~ ~ ~ RecipesUsed
clone ~ ~ ~ ~ ~ ~ ~ 255 ~
loot replace block ~ 255 ~ container.0 loot cpp:furnace/furnace
data modify block ~ 255 ~ Items[{Slot:0b}].Slot set value 2b
data modify block ~ ~ ~ Items append from block ~ 255 ~ Items[{Slot:2b}]
setblock ~ 255 ~ air
</pre>
<pre class="file" id="cpp/loot_tables/furnace/furnace">cpp/loot_tables/furnace/furnace.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:alternatives",
          "children": [
            {
              "conditions": [
                {
                  "condition": "minecraft:location_check",
                  "predicate": {
                    "block": {
                      "nbt": "{Items:[{Slot:0b,tag:{id:'cpp:clay_bucket'}}]}"
                     }
                   }
                 }
               ],
               "type": "minecraft:item",
               "name": "minecraft:bucket"
            },
            {
              "conditions": [
                {
                  "condition": "minecraft:location_check",
                  "predicate": {
                    "block": {
                      "nbt": "{Items:[{Slot:0b,tag:{id:'cpp:lycoris_radiata'}}]}"
                     }
                   }
                 }
               ],
               "type": "minecraft:item",
               "name": "minecraft:red_dye"
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<p>修改熔炉的火焰外观。</p>
<pre class="file" id="cpp/functions/furnace/lit_true">cpp:furnace/lit_true</pre>
<pre>
data modify storage cpp:furnace {} set from block ~ ~ ~ {}
execute if block ~ ~ ~ furnace[facing=east] run setblock ~ ~ ~ furnace[lit=true,facing=east]
execute if block ~ ~ ~ furnace[facing=west] run setblock ~ ~ ~ furnace[lit=true,facing=west]
execute if block ~ ~ ~ furnace[facing=south] run setblock ~ ~ ~ furnace[lit=true,facing=south]
execute if block ~ ~ ~ furnace[facing=north] run setblock ~ ~ ~ furnace[lit=true,facing=north]
data modify block ~ ~ ~ {} set from storage cpp:furnace {}
</pre>
<pre class="file" id="cpp/functions/furnace/lit_false">cpp:furnace/lit_false</pre>
<pre>
data modify storage cpp:furnace {} set from block ~ ~ ~ {}
execute if block ~ ~ ~ furnace[facing=east] run setblock ~ ~ ~ furnace[lit=false,facing=east]
execute if block ~ ~ ~ furnace[facing=west] run setblock ~ ~ ~ furnace[lit=false,facing=west]
execute if block ~ ~ ~ furnace[facing=south] run setblock ~ ~ ~ furnace[lit=false,facing=south]
execute if block ~ ~ ~ furnace[facing=north] run setblock ~ ~ ~ furnace[lit=false,facing=north]
data modify block ~ ~ ~ {} set from storage cpp:furnace {}
</pre>
<p>对于烟熏炉和高炉，操作是类似的，但是需要每次增加cppTick 2。营火由于会判断材料是否合法，因此无法用该方法。</p>

<h2 id="NBT酿造">§8.5 NBT酿造</h2>
<p>类似于自定义烧炼的方法，我们可以自定义酿造。但是由于酿造台的限制，酿造材料必须为原版酿造材料物品，待酿造的物品只能为药水或玻璃瓶。除了红石、萤石、火药、龙息外，建议使用兔子腿，因为兔子腿只有酿造功能。</p>
<p>如果酿造材料和待酿造的物品本身就属于原版可酿造的配方，我们只需在酿造即将完成时，将药水替换掉即可。例如：使用大地之证 (兔子腿 <code>cpp:certification_of_earth</code>) 将粗制的药水酿造成有多重药水效果的大地药水（<code>potion_of_earth</code>），同时支持延长、加强、喷溅、滞留版本。</p>

<p>放置和探测酿造台的部分省略。</p>
<pre class="file">cpp:tick</pre>
<pre>
execute as @e[type=armor_stand,tag=cpp_brewing_stand] at @s run function <a href="#cpp/functions/brewing/tick">cpp:brewing/tick</a>
</pre>
<pre class="file" id="cpp/functions/brewing/tick">cpp:brewing/tick</pre>
<pre>
execute unless block ~ ~ ~ brewing_stand run kill @s
execute if block ~ ~ ~ brewing_stand{BrewTime:1s,Items:[{Slot:3b,tag:{id:"cpp:certification_of_earth"}}]} run function <a href="#cpp/functions/brewing/earth">cpp:brewing/earth</a>
execute if block ~ ~ ~ brewing_stand{BrewTime:1s,Items:[{Slot:3b,tag:{id:"cpp:redstone"}}]} if predicate cpp:brewing/long run function <a href="#cpp/functions/brewing/long">cpp:brewing/long</a>
execute if block ~ ~ ~ brewing_stand{BrewTime:1s,Items:[{Slot:3b,tag:{id:"cpp:glowstone_dust"}}]} if predicate cpp:brewing/strong run function <a href="#cpp/functions/brewing/strong">cpp:brewing/strong</a>
execute if block ~ ~ ~ brewing_stand{BrewTime:1s,Items:[{Slot:3b,tag:{id:"cpp:gunpowder"}}]} if predicate cpp:brewing/splash run function <a href="#cpp/functions/brewing/splash">cpp:brewing/splash</a>
execute if block ~ ~ ~ brewing_stand{BrewTime:1s,Items:[{Slot:3b,tag:{id:"cpp:dragon_breath"}}]} if predicate cpp:brewing/lingering run function <a href="#cpp/functions/brewing/lingering">cpp:brewing/lingering</a>
</pre>
<p>我们在大地药水中添加 <code>Potion</code>，这样后续可以实现延长、加强、喷溅、投掷版本的酿造。</p>
<pre class="file" id="cpp/loot_tables/potion_of_dirt">cpp/loot_tables/potion_of_dirt.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "item",
          "name": "minecraft:potion",
          "functions": [
            {
              "function": "set_nbt",
              "tag": "{Potion:'minecraft:leaping',CustomPotionColor:14137114,display:{Name:'{\"translate\":\"item.ex.potion_of_earth\"}'},CustomPotionEffects:[{Id:3b,Duration:3600}],id:'cpp:potion_of_earth'}"
            }
          ]
        }
      ]
    }
  ]
}
</pre>

<pre class="file" id="cpp/functions/brewing/earth">cpp:brewing/earth</pre>
<pre>
loot replace entity @s weapon.mainhand 1 loot cpp:potion_of_earth
data modify block ~ ~ ~ Items[{tag:{Potion:"minecraft:awkward"}}].tag set from entity @s HandItems[0].tag
loot replace entity @s weapon.mainhand 1 loot minecraft:
execute store result block ~ ~ ~ Items[{Slot:3b}].Count byte 0.999 run data get block ~ ~ ~ Items[{Slot:3b}].Count
</pre>

<pre class="file" id="cpp/predicates/brewing/long">cpp/predicates/brewing/long</pre>
<pre>
{
  "condition": "minecraft:alternative",
  "terms": [
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{Potion:'minecraft:night_vision'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{Potion:'minecraft:invisibility'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{Potion:'minecraft:leaping'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{Potion:'minecraft:fire_resistance'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{Potion:'minecraft:swiftness'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{Potion:'minecraft:slowness'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{Potion:'minecraft:turtle_master'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{Potion:'minecraft:water_breathing'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{Potion:'minecraft:poison'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{Potion:'minecraft:regeneration'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{Potion:'minecraft:strength'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{Potion:'minecraft:weakness'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:0b,tag:{Potion:'minecraft:slow_falling'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:1b,tag:{Potion:'minecraft:night_vision'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:1b,tag:{Potion:'minecraft:invisibility'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:1b,tag:{Potion:'minecraft:leaping'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:1b,tag:{Potion:'minecraft:fire_resistance'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:1b,tag:{Potion:'minecraft:swiftness'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:1b,tag:{Potion:'minecraft:slowness'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:1b,tag:{Potion:'minecraft:turtle_master'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:1b,tag:{Potion:'minecraft:water_breathing'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:1b,tag:{Potion:'minecraft:poison'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:1b,tag:{Potion:'minecraft:regeneration'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:1b,tag:{Potion:'minecraft:strength'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:1b,tag:{Potion:'minecraft:weakness'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:1b,tag:{Potion:'minecraft:slow_falling'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:2b,tag:{Potion:'minecraft:night_vision'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:2b,tag:{Potion:'minecraft:invisibility'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:2b,tag:{Potion:'minecraft:leaping'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:2b,tag:{Potion:'minecraft:fire_resistance'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:2b,tag:{Potion:'minecraft:swiftness'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:2b,tag:{Potion:'minecraft:slowness'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:2b,tag:{Potion:'minecraft:turtle_master'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:2b,tag:{Potion:'minecraft:water_breathing'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:2b,tag:{Potion:'minecraft:poison'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:2b,tag:{Potion:'minecraft:regeneration'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:2b,tag:{Potion:'minecraft:strength'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:2b,tag:{Potion:'minecraft:weakness'}}]}"
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "nbt": "{Items:[{Slot:2b,tag:{Potion:'minecraft:slow_falling'}}]}"
        }
      }
    }
  ]
}
</pre>
<p>处理延长版药水时，还需要一并处理原版酿造的药水。加强、喷溅、投掷情形类似处理即可。</p>
<pre class="file" id="cpp/functions/brewing/long">cpp:brewing/long</pre>
<pre>
loot replace entity @s weapon.mainhand 1 loot cpp:potion_of_long_earth
data modify block ~ ~ ~ Items[{tag:{id:"cpp:potion_of_earth}}].tag set from entity @s HandItems[0].tag
loot replace entity @s weapon.mainhand 1 loot minecraft:air
data modify block ~ ~ ~ Items:[{tag:{Potion:"minecraft:night_vision"}}]}.tag.Potion set value "minecraft:long_night_vision"
data modify block ~ ~ ~ Items:[{tag:{Potion:"minecraft:invisibility"}}]}.tag.Potion set value "minecraft:long_invisibility"
data modify block ~ ~ ~ Items:[{tag:{Potion:"minecraft:leaping"}}]}.tag.Potion set value "minecraft:long_leaping"
data modify block ~ ~ ~ Items:[{tag:{Potion:"minecraft:fire_resistance"}}]}.tag.Potion set value "minecraft:long_fire_resistance"
data modify block ~ ~ ~ Items:[{tag:{Potion:"minecraft:swiftness"}}]}.tag.Potion set value "minecraft:long_swiftness"
data modify block ~ ~ ~ Items:[{tag:{Potion:"minecraft:slowness"}}]}.tag.Potion set value "minecraft:long_slowness"
data modify block ~ ~ ~ Items:[{tag:{Potion:"minecraft:turtle_master"}}]}.tag.Potion set value "minecraft:long_turtle_master"
data modify block ~ ~ ~ Items:[{tag:{Potion:"minecraft:water_breathing"}}]}.tag.Potion set value "minecraft:long_water_breathing"
data modify block ~ ~ ~ Items:[{tag:{Potion:"minecraft:poison"}}]}.tag.Potion set value "minecraft:long_poison"
data modify block ~ ~ ~ Items:[{tag:{Potion:"minecraft:regeneration"}}]}.tag.Potion set value "minecraft:long_regeneration"
data modify block ~ ~ ~ Items:[{tag:{Potion:"minecraft:strength"}}]}.tag.Potion set value "minecraft:long_strength"
data modify block ~ ~ ~ Items:[{tag:{Potion:"minecraft:weakness"}}]}.tag.Potion set value "minecraft:long_weakness"
data modify block ~ ~ ~ Items:[{tag:{Potion:"minecraft:slow_falling"}}]}.tag.Potion set value "minecraft:long_slow_falling"}
execute store result block ~ ~ ~ Items[{Slot:3b}].Count byte 0.999 run data get block ~ ~ ~ Items[{Slot:3b}].Count
item entity @s weapon.mainhand replace air
</pre>

<p>如果酿造材料和待酿造的物品不属于原版可酿造的配方，我们需要在二者均进入酿造台时，将其物品修改为具有相同纹理名称的、可以实现酿造的物品。当物品进入背包时，将其改回原物品。酿造即将完成时，检测相应NBT是否来自指定的物品，并修改产物。</p>


<h1 id="植物">§9 植物</h1>

<p>我们使用寻常作物来实现自定义作物。在相应的方块处放置带有自定义物品模型的盔甲架来实现其外观的不同，并高频判断和重置其生长状态来确定生长。模型可以选择盖住原方块模型，或删除原方块模型并将原作物当做自定义作物实现（会生成盔甲架实体）。如果自定义作物的纹理没有覆盖原来的方块，就会导致自定义的作物处，既有自定义作物的纹理，又有原本的作物纹理。解决方法之一是限定自定义作物模型包含原有的作物模型，另一种是删除原有方块纹理并在原方块处放置对应纹理的盔甲架解决。</p>

<table><thead><tr>
    <th>作物</th>
    <th>方块需求</th>
    <th>可使用骨粉</th>
    <th>模型处理</th>
    <th>特点</th>
    <th>用途</th>
  </tr></thead><tbody>
  <tr>
    <th>小麦、胡萝卜、马铃薯、甜菜根、瓜梗</th>
    <td>耕地</td>
    <td>是</td>
    <td>瓜梗模型最小，自定义模型只要比其大即可。</td>
    <td>瓜梗模型太小了很难破坏。</td>
    <td>通常作物、瓜类作物</td>
  </tr>
  <tr>
    <th>树苗</th>
    <td>任意土</td>
    <td>是</td>
    <td>模型较大，需要删除原模型，由于金合欢树苗出现场合最少，因此以金合欢为宜。深色橡木由于其需要2×2才可生长也有一定优势。</td>
    <td>有几率在一刻内直接生长为大树</td>
    <td>花卉、树</td>
  </tr>
  <tr>
    <th>甘蔗、仙人掌</th>
    <td>沙子</td>
    <td>否</td>
    <td>可以用较粗的类似甘蔗的模型，或完整方块模型来覆盖。</td>
    <td>需要处理上方一格方块，无法避免玩家手动叠方块</td>
    <td>甘蔗类</td>
  </tr>
  <tr>
    <th>草、蕨</th>
    <td>任意土</td>
    <td>是</td>
    <td>可以用较粗的类似草的模型，或完整方块模型来覆盖。</td>
    <td>需要处理上方一格方块，无法避免玩家手动叠方块</td>
    <td>甘蔗类</td>
  </tr>
  <tr>
    <th>可可豆</th>
    <td>丛林木</td>
    <td>是</td>
    <td>可以用略大的方形模型来覆盖</td>
    <td>可以添加标签来支持种植在其它方块侧</td>
    <td>树生类</td>
  </tr>
  <tr>
    <th>竹子、浆果丛、海草、海带</th>
    <td>-</td>
    <td>部分</td>
    <td>几乎无可能</td>
    <td>模型随机、性质特殊、水生难使用</td>
    <td>-</td>
  </tr>
  <tr>
    <th>屏障</th>
    <td>任意</td>
    <td>否</td>
    <td>任意</td>
    <td>无法直接破坏，需要借助其它方式；需要手动实现生长过程</td>
    <td>任意</td>
  </tr>
  <tr>
    <th>任意</th>
    <td>任意</td>
    <td>否</td>
    <td>完整方块模型</td>
    <td>需要手动实现生长过程，一般无法瞬间破坏</td>
    <td>任意</td>
  </tr>
</tbody></table>

<p>可以看出，较便捷的只有瓜梗+模型覆盖、金合欢/深色橡木树苗+删除原模型、任意方块+完整模型三种做法。对于第二种做法，我们还需要修改村庄等结构中相应的模型，而且在玩家大规模种植时会生成大量实体。</p>

<p>另一种实现方式即使用<a href="#命令方块替换法">§6.3 命令方块替换法</a>来放置，只需在放置完成后检测下方不是土时将其破坏掉即可。这种方法较为简单，缺点是物品缺少树苗的诸如可作为燃料、可堆肥的特性。</p>

<h2 id="作物">§9.1 作物</h2>

<p class="ex">种植铁种子，收获种子和铁锭，可由骨粉催熟。种下后，探测位置放置盔甲架。破坏时，修改附近掉落物。</p>
<pre class="file" id="cpp/functions/advancements/plants/iron_seeds">cpp:advancements/plants/iron_seeds</pre>
<pre>
{
  "parent": "cpp:plants/root",
  "criteria": {
    "iron_seeds": {
      "trigger": "minecraft:placed_block",
      "conditions": {
        "item": {
          "nbt":"{id:'cpp:iron_seeds'}"
        }
      }
    }
  },
  "rewards": {
    "function": "cpp:plants/plants/iron_seeds"
  }
}
</pre>

<pre class="file">cpp:tick</pre>
<pre>
execute as @e[type=armor_stand,tag=cpp_beetroots_plants] at @s unless block ~ ~ ~ beetroots run function <a href="#cpp/functions/plants/break/beetroots">cpp:plants/break/beetroots</a>
</pre>
<pre class="file" id="cpp/functions/plants/break/beetroots">cpp:plants/break/beetroots</pre>
<pre>
execute as @s[tag=cpp_iron_seeds] as @e[type=item,nbt={Item:{id:"minecraft:beetroot_seeds"},Age:0s},distance=..1] run data merge entity @s {Item:{tag:{HideFlags:63,Enchantments:[{}],display:{Name:'{"translate":"item.ex.iron_seeds"}'},id:"cpp:iron_seeds"}}}
execute as @s[tag=cpp_iron_seeds] as @e[type=item,nbt={Item:{id:"minecraft:beetroot"},Age:0s},distance=..1] run data merge entity @s {Item:{id:"minecraft:iron_ingot"}}
</pre>

<p>实际上，我们也可以通过盔甲架手持物品来实现自定义纹理的作物。</p>

<h2 id="花草">§9.2 花草</h2>
<p>我们使用金合欢树苗作为花草原型。方块的放置部分我们省略，只需要注意花草的模型通常和物品模型是不同的，因此在放置后需要修改CustomModelData，破坏情形也是同理。</p>
<p class="ex">放置花草种子，长大后收获成熟的花草。</p>
<pre class="file">cpp:tick</pre>
<pre>
execute as @e[type=armor_stand,tag=cpp_plants] at @s run function <a href="#cpp/functions/plants/tick">cpp:plants/tick</a>
</pre>
<pre class="file" id="cpp/functions/plants/tick">cpp:plants/tick</pre>
<pre>
<span class="comment"># 破坏</span>
execute unless block ~ ~ ~ acacia_sapling run function <a href="#cpp/functions/block/break/acacia_sapling">cpp:block/break/acacia_sapling</a>
<span class="comment"># 树生长</span>
execute as @s[tag=!cpp_acacia_sapling] if block ~ ~ ~ acacia_sapling[stage=1] run function <a href="#cpp/functions/plants/type">cpp:plants/type</a>
</pre>
<pre class="file" id="cpp/functions/plants/type">cpp:plants/type</pre>
<pre>
setblock ~ ~ ~ acacia_sapling
execute as @s[tag=cpp_crops] run function <a href="#cpp/functions/plants/crops/grow">cpp:plants/crops/grow</a>
execute as @s[tag=cpp_trees] run function <a href="#cpp/functions/plants/trees/grow">cpp:plants/trees/grow</a>
</pre>
<p>树木的处理见下一节，我们这里只处理花草部分。当花草长到最后一个阶段时，我们将其物品改成成熟的花草，以替代原有的花草种子。</p>
<pre class="file" id="cpp/functions/plants/crops/grow">cpp:plants/crops/grow</pre>
<pre>
execute store result score #t cppValue run data get entity @s ArmorItems[3].tag.CustomModelData
execute if score #t cppValue matches 12975001..12975060 run scoreboard players add #t cppValue 20
execute if score #t cppValue matches 12975061 run loot replace entity @s armor.head 1 loot cpp:lycoris_radiata
execute if score #t cppValue matches 12975062 run loot replace entity @s armor.head 1 loot cpp:trifolium
execute if score #t cppValue matches 12975063 run loot replace entity @s armor.head 1 loot cpp:blackthorn
execute if score #t cppValue matches 12975064 run loot replace entity @s armor.head 1 loot cpp:cattail
execute if score #t cppValue matches 12975065 run loot replace entity @s armor.head 1 loot cpp:marigold
execute if score #t cppValue matches 12975066 run loot replace entity @s armor.head 1 loot cpp:hibiscus
execute if score #t cppValue matches 12975067 run loot replace entity @s armor.head 1 loot cpp:hyacinth
execute if score #t cppValue matches 12975068 run loot replace entity @s armor.head 1 loot cpp:calamus
execute if score #t cppValue matches 12975069 run loot replace entity @s armor.head 1 loot cpp:wild_lilium
execute if score #t cppValue matches 12975070 run loot replace entity @s armor.head 1 loot cpp:bauhinia
execute if score #t cppValue matches 12975071 run loot replace entity @s armor.head 1 loot cpp:fluffy_grass
execute if score #t cppValue matches 12975072 run loot replace entity @s armor.head 1 loot cpp:gerbera
execute if score #t cppValue matches 12975073 run loot replace entity @s armor.head 1 loot cpp:esparto
execute if score #t cppValue matches 12975074 run loot replace entity @s armor.head 1 loot cpp:glow_forsythia
execute if score #t cppValue matches 12975075 run loot replace entity @s armor.head 1 loot cpp:glazed_shade
execute if score #t cppValue matches 12975076 run loot replace entity @s armor.head 1 loot cpp:stelera
execute if score #t cppValue matches 12975077 run loot replace entity @s armor.head 1 loot cpp:forage_crystal
execute if score #t cppValue matches 12975078 run loot replace entity @s armor.head 1 loot cpp:isorchid
execute if score #t cppValue matches 12975079 run loot replace entity @s armor.head 1 loot cpp:burning_chrysanthe
execute if score #t cppValue matches 12975080 run loot replace entity @s armor.head 1 loot cpp:oxalis
execute if score #t cppValue matches 12975021..12975080 store result entity @s ArmorItems[3].tag.CustomModelData int 1 run scoreboard players get #t cppValue
</pre>

<h2 id="树">§9.3 树</h2>

<p class="ex">种下矿石树树苗，然后会长大。长大后的树叶会逐渐变为矿石。</p>
<pre class="file" id="cpp/functions/plants/trees/grow">cpp:plants/trees/grow</pre>
<pre>
setblock ~ ~ ~ acacia_sapling
execute store result score #t cppValue run data get entity @s ArmorItems[3].tag.CustomModelData
scoreboard players add @s cppValue 1
execute if score @s cppValue >= $modTreeAgeMax exConfig if score #t cppValue matches 12976002 run function <a href="#cpp/functions/plants/trees/ore">cpp:plants/trees/ore</a>
</pre>
<pre class="file" id="cpp/functions/plants/trees/ore">cpp:plants/trees/ore</pre>
<pre>
execute positioned ~-2 ~3 ~-2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-2 ~3 ~-1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-2 ~3 ~ run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-2 ~3 ~1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-2 ~3 ~2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-1 ~3 ~-2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-1 ~3 ~-1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-1 ~3 ~ run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-1 ~3 ~1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-1 ~3 ~2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~ ~3 ~-2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~ ~3 ~-1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~ ~3 ~1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~ ~3 ~2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~1 ~3 ~-2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~1 ~3 ~-1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~1 ~3 ~ run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~1 ~3 ~1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~1 ~3 ~2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~2 ~3 ~-2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~2 ~3 ~-1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~2 ~3 ~ run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~2 ~3 ~1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~2 ~3 ~2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}

execute positioned ~-2 ~4 ~-2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-2 ~4 ~-1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-2 ~4 ~ run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-2 ~4 ~1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-2 ~4 ~2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-1 ~4 ~-2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-1 ~4 ~-1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-1 ~4 ~ run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-1 ~4 ~1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-1 ~4 ~2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~ ~4 ~-2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~ ~4 ~-1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~ ~4 ~1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~ ~4 ~2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~1 ~4 ~-2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~1 ~4 ~-1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~1 ~4 ~ run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~1 ~4 ~1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~1 ~4 ~2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~2 ~4 ~-2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~2 ~4 ~-1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~2 ~4 ~ run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~2 ~4 ~1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~2 ~4 ~2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}

execute positioned ~-2 ~5 ~ run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-1 ~5 ~-1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-1 ~5 ~ run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~-1 ~5 ~1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~ ~5 ~-2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~ ~5 ~-1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~ ~5 ~1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~ ~5 ~2 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~1 ~5 ~-1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~1 ~5 ~ run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~1 ~5 ~1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~2 ~5 ~ run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}

execute positioned ~-1 ~6 ~ run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~ ~6 ~-1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~ ~6 ~ run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~ ~6 ~1 run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}
execute positioned ~1 ~6 ~ run summon armor_stand ~ ~ ~ {Invulnerable:1b,Invisible:1b,Marker:1b,NoGravity:1b,Small:1b,DisabledSlots:7967,Tags:["cpp_block","cpp_leaves","cpp_need_fire","cpp_leaves_on_tree","cpp_ore_leaves"],Fire:32767s}

loot replace entity @e[type=armor_stand,tag=cpp_ore_leaves,distance=..20] armor.head 1 loot cpp:ore_leaves
execute at @e[type=armor_stand,tag=cpp_ore_leaves,distance=..20] if block ~ ~ ~ #minecraft:leaves run setblock ~ ~ ~ acacia_leaves replace
execute at @e[type=armor_stand,tag=cpp_ore_leaves,distance=..20] run setblock ~ ~ ~ acacia_leaves keep
kill @s
setblock ~ ~ ~ air
fill ~ ~ ~ ~ ~5 ~ spruce_log replace #minecraft:leaves
fill ~ ~ ~ ~ ~5 ~ spruce_log keep
</pre>
<p>然后我们处理树叶转化。我们使用20刻一次的函数。</p>
<pre class="file">cpp:tick20</pre>
<pre>
execute store result score #rts cppValue run gamerule randomTickSpeed
execute store result score #rtsno cppValue if entity @e[type=armor_stand,tag=cpp_leaves_on_tree]
scoreboard players operation #rtsno cppValue *= #rts cppValue
scoreboard players operation #leaves_rts cppValue += #rtsno cppValue
execute if score #leaves_rts cppValue >= $modLeavesThreshold exConfig as @e[type=armor_stand,tag=cpp_leaves_on_tree,sort=random,limit=1] at @s run function <a href="#cpp/functions/plants/leaves/type">cpp:plants/leaves/type</a>
schedule function <a href="#cpp/functions/tick20">cpp:tick20</a> 20t
</pre>
<pre class="file" id="cpp/functions/plants/leaves/type">cpp:plants/leaves/type</pre>
<pre>
execute as @s[tag=cpp_ore_leaves] run function <a href="#cpp/functions/plants/leaves/ore">cpp:plants/leaves/ore</a>
execute as @s[tag=cpp_fruit_leaves] if block ~ ~-1 ~ #cpp:air run function <a href="#cpp/functions/plants/leaves/fruit">cpp:plants/leaves/fruit</a>
scoreboard players set #leaves_rts cppValue 0
</pre>
<pre class="file" id="cpp/functions/plants/leaves/ore">cpp:plants/leaves/ore</pre>
<pre>
loot replace entity @s weapon.mainhand 1 loot cpp:misc/ore_leaves
execute as @s[nbt={HandItems:[{id:"minecraft:ancient_debris"},{}]}] run setblock ~ ~ ~ ancient_debris
execute as @s[nbt={HandItems:[{id:"minecraft:emerald_ore"},{}]}] run setblock ~ ~ ~ emerald_ore
execute as @s[nbt={HandItems:[{id:"minecraft:diamond_ore"},{}]}] run setblock ~ ~ ~ diamond_ore
execute as @s[nbt={HandItems:[{id:"minecraft:lapis_ore"},{}]}] run setblock ~ ~ ~ lapis_ore
execute as @s[nbt={HandItems:[{id:"minecraft:redstone_ore"},{}]}] run setblock ~ ~ ~ redstone_ore
execute as @s[nbt={HandItems:[{id:"minecraft:gold_ore"},{}]}] run setblock ~ ~ ~ gold_ore
execute as @s[nbt={HandItems:[{id:"minecraft:nether_quartz_ore"},{}]}] run setblock ~ ~ ~ nether_quartz_ore
execute as @s[nbt={HandItems:[{id:"minecraft:iron_ore"},{}]}] run setblock ~ ~ ~ iron_ore
execute as @s[nbt={HandItems:[{id:"minecraft:coal_ore"},{}]}] run setblock ~ ~ ~ coal_ore
kill @s
</pre>


<h1 id="物品与实体处理">§10 物品与实体处理</h1>
<p>本节内容较杂，主要包括常见的一些物品与实体处理方式。</p>


<h2 id="修改玩家背包">§10.1 修改玩家背包</h2>

<p>在1.17的 <code>item</code> 命令出现之前，我们无法直接对玩家的背包进行修改，想要修改玩家背包就必须借助其它方式。</p>

<p>一种方式是将修改后的物品信息复制到生物头部，并修改生物的死亡战利品表NBT。在战利品表中穷举获得该物品 <code>id</code> 和数量，并使用 <code>copy_nbt</code> 函数来将头部物品的NBT复制到战利品的NBT中。见 <a href="https://www.mcbbs.net/thread-837334-1-1.html">关于如何绕过moj不让改玩家的限制</a>。</p>

<pre class="file" id="cpp/loot_tables/misc/loot">cpp/loot_tables/misc/loot</pre>
<pre>
{
  "type": "entity",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:alternatives",
          "children": [
            {
              "type": "item",
              "name": "minecraft:andesite",
              "conditions": [
                {
                  "condition": "minecraft:entity_properties",
                  "entity": "this",
                  "predicate": {
                    "nbt": "{ArmorItems:[{},{},{}{id:'minecraft:andesite'}}"
                  }
                }
              ]
            },
            [中间省略其它物品的穷举过程]
            {
              "type": "item",
              "name": "minecraft:zombie_head",
              "conditions": [
                {
                  "condition": "minecraft:entity_properties",
                  "entity": "this",
                  "predicate": {
                    "nbt": "{ArmorItems:[{},{},{}{id:'minecraft:zombie_head'}}"
                  }
                }
              ]
            }
          ],
          functions": [
            {
              "function": "minecraft:set_count",
              "count": 2,
              "conditions": [
                {
                  "condition": "minecraft:entity_properties",
                  "entity": "this",
                  "predicate": {
                    "nbt": "{ArmorItems:[{},{},{},{Count:2b}]}"
                  }
                }
              ]
            },
            [中间省略其它数量的穷举过程]
            {
              "function": "minecraft:set_count",
              "count": 64,
              "conditions": [
                {
                  "condition": "minecraft:entity_properties",
                  "entity": "this",
                  "predicate": {
                    "nbt": "{ArmorItems:[{},{},{},{Count:64b}}"
                  }
                }
              ]
            },
            {
              "function": "minecraft:copy_nbt",
              "source": "this",
              "ops": [
                {
                  "source": "ArmorItems[3].tag",
                  "target": "{}",
                  "op": "merge"
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}
</pre>

<p>最后我们使用 <code>loot</code> 函数来将战利品表物品输出到玩家背包中。可以看出，该方法使用的战利品表非常长，而且需要根据版本更新或模组内容添加新的物品 <code>id</code>。这里我们提及一个可能的误区，一般生物的装备和手持物并不会出现在生物的战利品表中，想要通过直接 <code>loot ... kill</code> 获取生物的装备或手持物是不可能的。</p>

<p>另一种方式是对潜影盒战利品表使用项目 <code>dynamic</code>，该项目配合 <code>"name": "minecraft:contents"</code> 可以将潜影盒内物品作为战利品表输出。</p>

<pre class="file" id="minecraft/loot_tables/blocks/shulker_box">minecraft/loot_tables/blocks/shulker_box.json</pre>
<pre>
{
  "type": "minecraft:block",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:alternatives",
          "children": [
            {
              "type": "minecraft:dynamic",
              "name": "minecraft:contents",
              "conditions": [
                {
                  "condition": "minecraft:match_tool",
                  "predicate": {
                    "nbt":"{drop_content:1b}"
                  }
                }
              ]
            },
            {
              "type": "minecraft:item",
              "functions": [
                {
                  "function": "minecraft:copy_name",
                  "source": "block_entity"
                },
                {
                  "function": "minecraft:copy_nbt",
                  "source": "block_entity",
                  "ops": [
                    {
                      "source": "Lock",
                      "target": "BlockEntityTag.Lock",
                      "op": "replace"
                    },
                    {
                      "source": "LootTable",
                      "target": "BlockEntityTag.LootTable",
                      "op": "replace"
                    },
                    {
                      "source": "LootTableSeed",
                      "target": "BlockEntityTag.LootTableSeed",
                      "op": "replace"
                    }
                  ]
                },
                {
                  "function": "minecraft:set_contents",
                  "entries": [
                    {
                      "type": "minecraft:dynamic",
                      "name": "minecraft:contents"
                    }
                  ]
                }
              ],
              "name": "minecraft:shulker_box"
            }
          ]
        }
      ]
    }
  ]
}
</pre>

<p>我们将物品复制到潜影盒内，然后使用命令 <code>loot ... mine ~ 255 ~ tnt{drop_content:1b}</code>。通常我们将这种辅助用的方块放置在 <code>255</code> 高度以免破坏地形和建筑。</p>

<p>除了用于修改玩家背包，该命令还可配合 <code>loot insert</code> 来将物品输出到容器内，并使物品尽量堆叠。这常用于机器的输出，见 <a href="#物品输出">物品输出</a>。</p>


<h2 id="耐久处理">§10.2 耐久处理</h2>

<p>有时候我们需要模拟使用工具的过程，但工具并没有真正被使用，耐久也没有被消耗。此时我们需要手动对其耐久进行处理。</p>
<p>我们将物品信息复制到存储区 <code>cpp:damage</code> 的 <code>Item</code> 中，然后使用断言判断是否减少耐久。最后判断其是否已经耐久耗尽，若耗尽则清除之。</p>

<pre class="file" id="cpp/functions/damage">cpp:damage</pre>
<pre>
execute store result score @s cppValue run data get entity @s SelectItem.tag.Enchantments[{id:"minecraft:unbreaking"}].lvl
execute store result score #damage cppValue run data get entity @s SelectedItem.tag.Damage
execute if predicate cpp:damage store result storage cpp:storage Damage int 1 run scoreboard players add #damage cppValue 1
item entity @s[nbt=!{SelectedItem:{tag:{Unbreakable:1b}}}] weapon.mainhand modify <a href="#cpp/item_modifiers/set_damage_score">cpp:set_damage_score</a>]
</pre>
<pre class="file" id="cpp/predicate/damage">cpp/predicate/damage.json</pre>
<pre>
{
  "condition": "minecraft:value_check",
  "value": {
    "type": "minecraft:uniform",
    "min": 0,
    "max": {
      "type": "score",
      "target": {
        "type": "context",
        "target": "this"
      },
      "score": "cppValue"
    }
  },
  "range": 0
}</pre>
<pre class="file" id="cpp/item_modifiers/set_damage_score">cpp/item_modifiers/set_damage_score.json</pre>
<pre>
{
  "function": "minecraft:copy_nbt",
  "source": {
    "type": "storage",
    "source": "cpp:storage"
  },
  "ops": [
    {
      "op": "replace",
      "source": "Damage",
      "target": "Damage"
    }
  ]
}</pre>

<p>对于1.17之前的版本，我们可以通过生成<code>0~耐久附魔等级</code>的随机数，并判断是否为0来确定是否消耗耐久，参考<a href="随机数">§10.1 随机数</a>。</p>

<h2 id="红石信号">§10.3 红石信号</h2>

<p>为了检测当前方块是否被强充能了，我们将所有能激活当前方块的红石元件和方块状态记录在断言文件中来判断。注意我们没有对当前方块是否完整进行检测。陷阱箱触发的红石信号也是无法直接探测到的。</p>

<pre class="file" id="cpp/predicates/power/strong">cpp/predicates/power/strong.json</pre>
<pre>
{
  "condition": "minecraft:alternative",
  "terms": [
    {
      "condition": "minecraft:location_check",
      "offsetY": -1,
      "predicate": {
        "block": {
          "blocks": ["minecraft:lever"],
          "state": {
            "powered": true,
            "face": "ceiling"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetY": 1,
      "predicate": {
        "block": {
          "blocks": ["minecraft:lever"],
          "state": {
            "powered": true,
            "face": "floor"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetX": 1,
      "predicate": {
        "block": {
          "blocks": ["minecraft:lever"],
          "state": {
            "powered": true,
            "face": "wall",
            "facing": "east"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetX": -1,
      "predicate": {
        "block": {
          "blocks": ["minecraft:lever"],
          "state": {
            "powered": true,
            "face": "wall",
            "facing": "west"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetZ": 1,
      "predicate": {
        "block": {
          "blocks": ["minecraft:lever"],
          "state": {
            "powered": true,
            "face": "wall",
            "facing": "south"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetZ": -1,
      "predicate": {
        "block": {
          "blocks": ["minecraft:lever"],
          "state": {
            "powered": true,
            "face": "wall",
            "facing": "north"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetY": -1,
      "predicate": {
        "block": {
          "tag": "minecraft:buttons",
          "state": {
            "powered": true,
            "face": "ceiling"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetY": 1,
      "predicate": {
        "block": {
          "tag": "minecraft:buttons",
          "state": {
            "powered": true,
            "face": "floor"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetX": 1,
      "predicate": {
        "block": {
          "tag": "minecraft:buttons",
          "state": {
            "powered": true,
            "face": "wall",
            "facing": "east"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetX": -1,
      "predicate": {
        "block": {
          "tag": "minecraft:buttons",
          "state": {
            "powered": true,
            "face": "wall",
            "facing": "west"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetZ": 1,
      "predicate": {
        "block": {
          "tag": "minecraft:buttons",
          "state": {
            "powered": true,
            "face": "wall",
            "facing": "south"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetZ": -1,
      "predicate": {
        "block": {
          "tag": "minecraft:buttons",
          "state": {
            "powered": true,
            "face": "wall",
            "facing": "north"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetY": -1,
      "predicate": {
        "block": {
          "blocks": ["minecraft:redstone_torch","minecraft:redstone_wall_torch"],
          "state": {
            "lit": true
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetY": -1,
      "predicate": {
        "block": {
          "blocks": ["minecraft:observer"],
          "state": {
            "powered": true,
            "facing": "down"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetY": 1,
      "predicate": {
        "block": {
          "blocks": ["minecraft:observer"],
          "state": {
            "powered": true,
            "facing": "up"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetX": 1,
      "predicate": {
        "block": {
          "blocks": ["minecraft:observer","minecraft:repeater","minecraft:comparator","minecraft:tripwire_hook"],
          "state": {
            "powered": true,
            "facing": "east"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetX": -1,
      "predicate": {
        "block": {
          "blocks": ["minecraft:observer","minecraft:repeater","minecraft:comparator","minecraft:tripwire_hook"],
          "state": {
            "powered": true,
            "facing": "west"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetZ": 1,
      "predicate": {
        "block": {
          "blocks": ["minecraft:observer","minecraft:repeater","minecraft:comparator","minecraft:tripwire_hook"],
          "state": {
            "powered": true,
            "facing": "south"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetZ": -1,
      "predicate": {
        "block": {
          "blocks": ["minecraft:observer","minecraft:repeater","minecraft:comparator","minecraft:tripwire_hook"],
          "state": {
            "powered": true,
            "facing": "north"
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetY": 1,
      "predicate": {
        "block": {
          "tag": "minecraft:wooden_pressure_plates",
          "state": {
            "powered": true
          }
        }
      }
    },
    {
      "condition": "minecraft:location_check",
      "offsetY": 1,
      "predicate": {
        "block": {
          "blocks": ["minecraft:stone_pressure_plate","minecraft:light_weighted_pressure_plate","minecraft:heavy_weighted_pressure_plate"],
          "state": {
            "powered": true
          }
        }
      }
    },
    {
      "condition": "minecraft:reference",
      "name": "cpp:power/has_power_block"
    }
  ]
}</pre>
<pre class="file" id="cpp/predicates/power/has_power_block">cpp/predicates/power/has_power_block.json</pre>
<pre>
[
  {
    "condition": "minecraft:location_check",
    "predicate": {
      "block": {
        "tag": "cpp:has_power"
      }
    }
  },
  {
    "condition": "minecraft:inverted",
    "term": {
      "condition": "minecraft:location_check",
      "predicate": {
        "block": {
          "state": {
            "power": "0"
          }
        }
      }
    }
  }
]
</pre>
<pre class="file" id="cpp/tags/blocks/has_power">cpp/tags/blocks/has_power.json</pre>
<pre>
{
  "replace": false,
  "values": [
    "minecraft:target",
    "minecraft:sculk_sensor"
  ]
}
</pre>

<p>弱充能情形更为繁琐。</p>

<p>想要产生一个红石信号，可以通过在当前位置放置红石块再放置空气来产生。注意保存当前方块的信息。这样的红石信号可以用于激活结构方块，因此可用于 <a href="世界生成">§11 世界生成</a>。</p>

<h2 id="方块交互">§10.4 方块交互</h2>

<p>与某些特定方块交互，可通过相应的交互判据的计分板来探测。如果仅需要右击而不打开，可对容器进行上锁，但玩家快捷栏上方会提示容器已上锁，需要使用资源包来消除；或者使用传送来实现强制关闭GUI，但画面会有闪烁感。</p>

<p class="ex">右键方块破坏器将其上方的石头变为砂砾，圆石变为沙子。方块破坏器为上锁的熔炉，且相应位置已有盔甲架标记。这里我们直接使用 <a href="#视线追踪法">视线追踪法</a>来获取方块破坏器位置。</p>

<pre class="file">cpp:load</pre>
<pre>
scoreboard objectives add cppBsdIntFur minecraft.custom:minecraft.interact_with_furnace
</pre>
<pre class="file">cpp:tick</pre>
<pre>
execute as @a[scores={cppBsdIntFur=1..}] at @s anchored eyes run function <a href="#cpp/functions/block_breaker/ray">cpp:block_breaker/ray</a>
</pre>
<pre class="file" id="cpp/functions/block_breaker/ray">cpp:block_breaker/ray</pre>
<pre>
execute if entity @s[distance=..7] unless block ~ ~ ~ furnace positioned ^ ^ ^0.005 anchored feet run function <a href="#cpp/functions/block_breaker/ray">cpp:block_breaker/ray</a>
execute if entity @s[distance=..7] if block ~ ~ ~ furnace{Lock:"zsx&lt;3wtt"} if block ~ ~1 ~ #cpp:block_breaker run function <a href="#cpp/functions/block_breaker/done">cpp:block_breaker/done</a>
scoreboard players reset @s cppBsdIntFur
</pre>
<pre class="file" id="cpp/tags/blocks/block_breaker">cpp/tags/blocks/block_breaker</pre>
<pre>
{
  "replace": false,
  "values": [
    "minecraft:stone",
    "minecraft:cobblestone",
  ]
}
</pre>
<pre class="file" id="cpp/functions/block_breaker/done">cpp:block_breaker/done</pre>
<pre>
execute if block ~ ~1 ~ stone run setblock ~ ~1 ~ gravel
execute if block ~ ~1 ~ cobblestone run setblock ~ ~1 ~ sand
</pre>

<p>同理，<a href="#插件">插件</a>中的插件安装也可以通过打开木桶的判据来实现。我们使用传送来实现强制关闭GUI。</p>

<pre class="file">cpp:load</pre>
<pre>
scoreboard objectives add cppOpenFrame minecraft.custom:minecraft.open_barrel
</pre>
<pre class="file">cpp:tick</pre>
<pre>
execute as @a[tag=machine_close_gui] at @s positioned ~ ~-256 ~ run function <a href="#cpp/functions/misc/close_gui_back">cpp:misc/close_gui_back</a>
execute as @a[scores={cppOpenFrame=1..}] if predicate <a href="#cpp/predicates/all_in_one_machine/hand_machine_plugin">cpp:all_in_one_machine/hand_machine_plugin</a> at @s anchored eyes run function <a href="#cpp/functions/all_in_one_machine/plugin/ray">cpp:all_in_one_machine/plugin/ray</a>
</pre>
<pre class="file" id="cpp/predicates/all_in_one_machine/hand_machine_plugin">cpp/predicates/all_in_one_machine/hand_machine_plugin.json</pre>
<pre>
{
  "condition": "minecraft:alternative",
  "terms": [
    {
      "condition": "minecraft:entity_properties",
      "entity": "this",
      "predicate": {
        "equipment": {
          "mainhand":{
            "nbt": "{macMachinePlugin:1b}"
          }
        }
      }
    },
    {
      "condition": "minecraft:entity_properties",
      "entity": "this",
      "predicate": {
        "equipment": {
          "offhand":{
            "nbt": "{macMachinePlugin:1b}"
          }
        }
      }
    }
  ]
}
</pre>
<pre class="file" id="cpp/functions/all_in_one_machine/plugin/ray">cpp:all_in_one_machine/plugin/ray</pre>
<pre>
execute as @s[distance=..6] if block ~ ~ ~ barrel align xyz positioned ~0.5 ~ ~0.5 run function <a href="#cpp/functions/all_in_one_machine/init">cpp:all_in_one_machine/init</a>
execute as @s[distance=..6] unless block ~ ~ ~ barrel positioned ^ ^ ^0.005 anchored feet run function <a href="#cpp/functions/all_in_one_machine/plugin/ray">cpp:all_in_one_machine/plugin/ray</a>
</pre>
<pre class="file" id="cpp/functions/all_in_one_machine/init">cpp:all_in_one_machine/init</pre>
<pre>
execute as @s[nbt=!{SelectedItem:{tag:{macMachinePlugin:1b}}}] run data modify storage cpp:plugin Item set from entity @s Inventory[{Slot:-106b}]
execute as @s[nbt={SelectedItem:{tag:{macMachinePlugin:1b}}}] run data modify storage cpp:plugin Item set from entity @s SelectedItem
execute if data storage cpp:plugin Item.tag{id:"cpp:high_pressure_plugin"} if entity @e[tag=machine_all_in_one_machine,distance=..0.5,limit=1,tag=!machine_high_pressure] run function <a href="#cpp/functions/all_in_one_machine/init/high_pressure">cpp:all_in_one_machine/init/high_pressure</a>
execute if data storage cpp:plugin Item.tag{id:"cpp:low_pressure_plugin"} if entity @e[tag=machine_all_in_one_machine,distance=..0.5,limit=1,tag=!machine_low_pressure] run function <a href="#cpp/functions/all_in_one_machine/init/low_pressure">cpp:all_in_one_machine/init/low_pressure</a>
execute if data storage cpp:plugin Item.tag{id:"cpp:high_temperature_plugin"} if entity @e[tag=machine_all_in_one_machine,distance=..0.5,limit=1,tag=!machine_high_temperature] run function <a href="#cpp/functions/all_in_one_machine/init/high_temperature">cpp:all_in_one_machine/init/high_temperature</a>
execute if data storage cpp:plugin Item.tag{id:"cpp:low_temperature_plugin"} if entity @e[tag=machine_all_in_one_machine,distance=..0.5,limit=1,tag=!machine_low_temperature] run function <a href="#cpp/functions/all_in_one_machine/init/low_temperature">cpp:all_in_one_machine/init/low_temperature</a>
execute as @s[tag=machine_plugin_used] at @s run function <a href="#cpp/functions/close_gui">cpp:close_gui</a>
tag @s[tag=machine_plugin_used] remove machine_plugin_used
</pre>
<pre class="file" id="cpp/functions/all_in_one_machine/init/high_pressure">cpp:all_in_one_machine/init/high_pressure</pre>
<pre>
tellraw @s [{"translate":"info.machine.high_pressure_plugin"}]
tag @s add machine_plugin_used
tag @e[tag=machine_all_in_one_machine,distance=..0.5,limit=1,tag=!machine_high_pressure] add machine_high_pressure
clear @s[tag=machine_plugin_used] minecraft:firework_star{id:"cpp:high_pressure_plugin"} 1
</pre>
<pre class="file" id="cpp/functions/misc/close_gui">cpp:misc/close_gui</pre>
<pre>
summon minecraft:marker ~ ~ ~ {Tags:["machine_close_gui_pos"],Duration:2}
summon minecraft:marker ^ ^ ^3 {Tags:["machine_close_gui_facing"],Duration:2}
tp @s ~ ~256 ~
tag @s add machine_close_gui
</pre>
<pre class="file" id="cpp/functions/misc/close_gui_back">cpp:misc/close_gui_back</pre>
<pre>
tp @s @e[type=marker,tag=machine_close_gui_pos,distance=..10,sort=nearest,limit=1]
tag @s remove machine_close_gui
execute at @s facing entity @e[type=marker,tag=machine_close_gui_facing,distance=..10,sort=nearest,limit=1] feet run tp ~ ~ ~
</pre>

<h2 id="生物移动">§10.5 生物移动</h2>

<p class="ex">手持绿宝石块的玩家吸引 <code>16</code> 米内的村民到自身位置。</p>

<pre class="file">cpp:tick</pre>
<pre>
tag @a remove cpp_player_hand_emerald_block
execute as @e[type=villager] at @s if entity @a[distance=1..16,predicate=<a href="#cpp/predicates/hand_emerald_block">cpp:hand_emerald_block</a>] run function <a href="#cpp/functions/misc/attract_villager">cpp:misc/attract_villager</a>
</pre>
<pre class="file" id="cpp/predicates/hand_emerald_block">cpp/predicates/hand_emerald_block.json</pre>
<pre>
{
  "condition": "minecraft:alternative",
  "terms": [
    {
      "condition": "minecraft:entity_properties",
      "entity": "this",
      "predicate": {
        "equipment": {
          "mainhand":{
            "items": ["minecraft:emerald_block"]
          }
        }
      }
    },
    {
      "condition": "minecraft:entity_properties",
      "entity": "this",
      "predicate": {
        "equipment": {
          "offhand":{
            "items": ["minecraft:emerald_block"]
          }
        }
      }
    }
  ]
}
</pre>
<pre class="file" id="cpp/functions/misc/attract_villager">cpp:misc/attract_villager</pre>
<pre>
tag @p[distance=1..16,predicate=<a href="#cpp/predicates/hand_emerald_block">cpp:hand_emerald_block</a>] add cpp_player_hand_emerald_block
tp @s ~ ~ ~ facing entity @p[tag=cpp_player_hand_emerald_block]
data merge entity @s {Motion:[0.0d,-1.0d,0.0d]}
execute facing entity @p[tag=cpp_player_hand_emerald_block] feet positioned ^ ^ ^0.75 unless block ~ ~ ~ #cpp:attract_through if block ~ ~1 ~ #cpp:air run data merge entity @s {Motion:[0.0d,1.0d,0.0d]}
execute store result score #temp0 cppValue run data get entity @p[tag=cpp_player_hand_emerald_block] Pos[0] 100
execute store result score #temp1 cppValue run data get entity @s Pos[0] 100
execute store result entity @s Motion[0] double 0.0005 run scoreboard players operation #temp0 cppValue -= #temp1 cppValue
execute store result score #temp0 cppValue run data get entity @p[tag=cpp_player_hand_emerald_block] Pos[2] 100
execute store result score #temp1 cppValue run data get entity @s Pos[2] 100
execute store result entity @s Motion[2] double 0.0005 run scoreboard players operation #temp0 cppValue -= #temp1 cppValue
</pre>
<pre class="file" id="cpp/tags/blocks/attract_through">cpp/tags/blocks/attract_through.json</pre>
<pre>
{
  "replace": false,
  "values": [
    "#cpp:fluid",
    "#minecraft:saplings",
    "minecraft:grass",
    "minecraft:fern",
    "minecraft:dead_bush",
    "minecraft:seagrass",
    "minecraft:sea_pickle",
    "#minecraft:small_flowers",
    "minecraft:brown_mushroom",
    "minecraft:red_mushroom",
    "minecraft:torch",
    "minecraft:end_rod",
    "minecraft:ladder",
    "minecraft:snow",
    "#minecraft:carpets",
    "minecraft:sunflower",
    "minecraft:lilac",
    "minecraft:rose_bush",
    "minecraft:peony",
    "minecraft:tall_grass",
    "minecraft:large_fern",
    "#minecraft:corals",
    "#minecraft:signs",
    "minecraft:vine",
    "minecraft:dead_tube_coral",
    "minecraft:dead_horn_coral",
    "minecraft:dead_fire_coral",
    "minecraft:dead_bubble_coral",
    "minecraft:dead_brain_coral",
    "minecraft:dead_tube_coral_fan",
    "minecraft:dead_horn_coral_fan",
    "minecraft:dead_fire_coral_fan",
    "minecraft:dead_bubble_coral_fan",
    "minecraft:dead_brain_coral_fan",
    "minecraft:lever",
    "minecraft:repeater",
    "minecraft:comparator",
    "#minecraft:wooden_pressure_plates",
    "minecraft:light_weighted_pressure_plate",
    "minecraft:heavy_weighted_pressure_plate",
    "#minecraft:buttons",
    "minecraft:redstone_torch",
    "minecraft:tripwire_hook",
    "minecraft:tripwire",
    "#minecraft:doors",
    "#minecraft:rails",
    "minecraft:redstone_wire",
    "#minecraft:walls",
    "#minecraft:fences",
    "minecraft:oak_fence_gate",
    "minecraft:spruce_fence_gate",
    "minecraft:birch_fence_gate",
    "minecraft:jungle_fence_gate",
    "minecraft:acacia_fence_gate",
    "minecraft:dark_oak_fence_gate"
  ]
}
</pre>

<p>这里我们进行了繁复的判断是为了让村民能够爬坡，但不能爬过栅栏类方块。如果是想要实现吸引物品掉落物的效果，则很多内容可以省略。</p>


<h2 id="交易">§10.6 交易</h2>
<p>使用村民或流浪商人交易是一种常见的特殊物品获得方式。对于村民，我们需要将村民的经验设定为 <code>250</code> 或更高以保证村民是大师，以避免其因工作方块而进行变化，导致设定的交易被覆盖或出现不想要的交易。对于流浪商人，我们需要设置 <code>DespawnDelay</code> 充分大以避免其消失。如果不希望交易产生经验值，需将 <code>rewardExp</code> 设置为 <code>0b</code>。通过让村民佩戴物品，可以让村民头部实现不同的外观，但是其它部位不能如此修改，使用佩戴在头部全身模型也会因村民头部移动而发生错乱。</p>

<p>建议使用战利品来随机生成村民的交易项。</p>

<pre class="file" id="trade/functions/load">trade:load</pre>
<pre>
function trade:tick20 20t
</pre>
<pre class="file" id="trade/functions/tick20">trade:tick20</pre>
<pre>
execute as @e[type=wandering_trader,tag=!trade_trade_added] run function trade:check
schedule function trade:tick20 20t
</pre>
<pre class="file" id="trade/functions/check">trade:check</pre>
<pre>
data merge entity @s {ArmorItems:[{},{},{},{id:"minecraft:carved_pumpkin",Count:1b,tag:{CustomModelData:12970051}}],ArmorDropChances:[-1.0f,-1.0f,-1.0f,-1.0f]}
data modify entity @s Offers.Recipes prepend value {buy:{id:"minecraft:stone",Count:64b},sell:{id:"minecraft:emerald",Count:1b},maxUses:12}
data modify entity @s Offers.Recipes append value {buy:{id:"minecraft:emerald",Count:64b},sell:{id:"minecraft:stone",Count:1b},maxUses:12}
loot replace entity @s weapon.mainhand 1 loot trade:trade/buy
data modify entity @s Offers.Recipes[0].buy.id set from entity @s HandItems[0].id
data modify entity @s Offers.Recipes[0].buy.Count set from entity @s HandItems[0].Count
loot replace entity @s weapon.mainhand 1 loot trade:trade/sell
data modify entity @s Offers.Recipes[9].sell.id set from entity @s HandItems[0].id
data modify entity @s Offers.Recipes[9].buy.Count set from entity @s HandItems[0].Count
item entity @s weapon.mainhand replace air
tag @s add trade_trade_added
</pre>
<pre class="file" id="trade/loot_tables/trade/buy">trade/loot_tables/trade/buy.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:oak_log",
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": {
                "type": "minecraft:uniform",
                "min": 36,
                "max": 40
              }
            }
          ]
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:spruce_log",
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": {
                "type": "minecraft:uniform",
                "min": 36,
                "max": 40
              }
            }
          ]
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:birch_log",
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": {
                "type": "minecraft:uniform",
                "min": 36,
                "max": 40
              }
            }
          ]
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:jungle_log",
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": {
                "type": "minecraft:uniform",
                "min": 36,
                "max": 40
              }
            }
          ]
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:acacia_log",
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": {
                "type": "minecraft:uniform",
                "min": 36,
                "max": 40
              }
            }
          ]
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:dark_oak_log",
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": {
                "type": "minecraft:uniform",
                "min": 36,
                "max": 40
              }
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<pre class="file" id="trade/loot_tables/trade/sell">trade/loot_tables/trade/sell.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:piston",
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": {
                "type": "minecraft:uniform",
                "min": 4,
                "max": 6
              }
            }
          ]
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:redstone_lamp",
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": {
                "type": "minecraft:uniform",
                "min": 4,
                "max": 6
              }
            }
          ]
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:tnt",
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": {
                "type": "minecraft:uniform",
                "min": 4,
                "max": 6
              }
            }
          ]
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:observer",
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": {
                "type": "minecraft:uniform",
                "min": 4,
                "max": 6
              }
            }
          ]
        }
      ]
    }
  ]
}
</pre>

<p>这样，我们便为每个流浪商人的最前面添加了交易 <code>36-40</code> 个原木换 <code>1</code> 个绿宝石，最后面添加了交易 <code>4-6</code> 个绿宝石换活塞、红石灯、TNT、观察者。</p>

<p>1.13版本可将村民的NBT修改为 <code>{VillagerData:{profession:"minecraft:none"}</code> 以确保村民不含交易。</p>

<h2 id="清理特定物品">§10.7 清理特定物品</h2>

<p>在自动种植、自动繁殖或放置方块等情形，我们需要对容器内的特定物品进行消耗。例如：当含有 <code>cpp:toughen_hand</code> 的物品展示框下方容器内有胡萝卜、金胡萝卜、蒲公英时，令附近的兔子进入繁殖状态并清除一个相应物品。</p>

<pre class="file">cpp:tick</pre>
<pre>
execute as @e[type=item_frame,nbt={Item:{tag:{id:"cpp:toughen_hand"}}}] at @s if entity @e[type=rabbit,distance=..9,nbt={Age:0,InLove:0}] run function <a href="#cpp/functions/toughen_hand/rabbit_check">cpp:toughen_hand/rabbit_check</a>
</pre>
<pre class="file" id="cpp/functions/toughen_hand/rabbit_check">cpp:toughen_hand/rabbit_check</pre>
<pre>
scoreboard players set @s cppValue 0
execute if data block ~ ~-1 ~ Items[{id:"minecraft:carrot"}] run scoreboard players set @s cppValue 1
execute if data block ~ ~-1 ~ Items[{id:"minecraft:golden_carrot"}] run scoreboard players set @s cppValue 2
execute if data block ~ ~-1 ~ Items[{id:"minecraft:dandelion"}] run scoreboard players set @s cppValue 3
execute if score @s cppValue matches 1.. run function <a href="#cpp/functions/toughen_hand/rabbit">cpp:toughen_hand/rabbit</a>
</pre>
<pre class="file" id="cpp/functions/toughen_hand/rabbit">cpp:toughen_hand/rabbit</pre>
<pre>
execute if score @s cppValue matches 1 run data modify storage cpp:toughen_hand Item set from block ~ ~-1 ~ Items[{id:"minecraft:carrot"}]
execute if score @s cppValue matches 2 run data modify storage cpp:toughen_hand Item set from block ~ ~-1 ~ Items[{id:"minecraft:golden_carrot"}]
execute if score @s cppValue matches 3 run data modify storage cpp:toughen_hand Item set from block ~ ~-1 ~ Items[{id:"minecraft:dandelion"}]
execute store result storage cpp:toughen_hand Item.Count byte 0.999 run data get storage cpp:toughen_hand Item.Count
data modify block ~ ~-1 ~ Items append from storage cpp:toughen_hand Item
data merge entity @e[type=item_framerabbit,distance=..9,nbt={Age:0,InLove:0},limit=1] {InLove:600}
</pre>

<p>注意到一点，<code>Items[{id:"minecraft:carrot"}]</code> 只会选择容器内的最后一个拥有胡萝卜的栏位。如果 <code>cpp:toughen_hand</code> 的物品被消耗完，则追加到容器的 <code>Items</code> 时，仍然会先覆盖已有的同 <code>Slot</code> 项，然后由于 <code>Count</code> 变为 <code>0</code> 而清除该栏位。</p>

<h2 id="连锁">§10.8 连锁</h2>

<p>当玩家使用原版镐时，破坏所有相连的矿石。</p>
<p>我们将允许使用连锁的工具添加至<code>cpp:mainhand/axe</code>等物品标签中，其中镐根据方块所需挖掘等级不同而划分为不同标签。相应可挖掘方块被记录在<code>cpp:chain/axe</code>等方块标签中。</p>

<pre class="file">cpp:tick</pre>
<pre>
execute as @a at @s at @e[type=item,nbt={Age:0s,PickupDelay:10s},distance=..6.5,limit=1] run function <a href="#cpp/functions/chain/init">cpp:chain/init</a>
</pre>
<pre class="file" id="cpp/functions/chain/init">cpp:chain/init</pre>
<pre>
execute store result score @s cppValue run data get entity @s SelectedItem.tag.Enchantments[{id:"minecraft:unbreaking"}].lvl
execute store result score #damage cppValue run data get entity @s SelectedItem.tag.Damage
function <a href="#cpp/functions/get_durality">cpp:get_durality</a>
execute if entity @s[nbt={SelectedItem:{tag:{Unbreakable:1b}}}] run scoreboard players set #max_durality cppValue 2147483647
scoreboard players set #mined cppValue 0
execute as @s[predicate=<a href="#cpp/predicates/mainhand/axe">cpp:mainhand/axe</a>] run function <a href="#cpp/functions/chain/axe/mark">cpp:chain/axe/mark</a>
execute if score #damage cppValue &lt; #max_durality cppValue as @s[predicate=<a href="#cpp/predicates/mainhand/shovel">cpp:mainhand/shovel</a>] run function <a href="#cpp/functions/chain/shovel/mark">cpp:chain/shovel/mark</a>
execute if score #damage cppValue &lt; #max_durality cppValue as @s[predicate=<a href="#cpp/predicates/mainhand/hoe">cpp:mainhand/hoe</a>] run function <a href="#cpp/functions/chain/hoe/mark">cpp:chain/hoe/mark</a>
execute if score #damage cppValue &lt; #max_durality cppValue as @s[predicate=<a href="#cpp/predicates/mainhand/pickaxe3">cpp:mainhand/pickaxe3</a>] run function <a href="#cpp/functions/chain/pickaxe3/mark">cpp:chain/pickaxe3/mark</a>
execute if score #damage cppValue &lt; #max_durality cppValue as @s[predicate=<a href="#cpp/predicates/mainhand/pickaxe2">cpp:mainhand/pickaxe2</a>] run function <a href="#cpp/functions/chain/pickaxe2/mark">cpp:chain/pickaxe2/mark</a>
execute if score #damage cppValue &lt; #max_durality cppValue as @s[predicate=<a href="#cpp/predicates/mainhand/pickaxe1">cpp:mainhand/pickaxe1</a>] run function <a href="#cpp/functions/chain/pickaxe1/mark">cpp:chain/pickaxe1/mark</a>
execute if score #damage cppValue &lt; #max_durality cppValue as @s[predicate=<a href="#cpp/predicates/mainhand/pickaxe">cpp:mainhand/pickaxe</a>] run function <a href="#cpp/functions/chain/pickaxe/mark">cpp:chain/pickaxe/mark</a>
execute store result storage cpp:_ Damage int 1 run scoreboard players get #damage cppValue
item entity @s[nbt=!{SelectedItem:{tag:{Unbreakable:1b}}}] weapon.mainhand modify <a href="#cpp/item_modifiers/chain_tool">cpp:chain_tool</a>
</pre>
<pre class="file" id="cpp/functions/chain/pickaxe1/mark">cpp:chain/pickaxe1/mark</pre>
<pre>
execute positioned ~1 ~ ~ if block ~ ~ ~ #cpp:chain/pickaxe1 run function <a href="#cpp/functions/chain/pickaxe1/damage">cpp:chain/pickaxe1/damage</a>
execute if score #damage cppValue &lt; #max_durality cppValue positioned ~-1 ~ ~ if block ~ ~ ~ #cpp:chain/pickaxe1 run function <a href="#cpp/functions/chain/pickaxe1/damage">cpp:chain/pickaxe1/damage</a>
execute if score #damage cppValue &lt; #max_durality cppValue positioned ~ ~1 ~ if block ~ ~ ~ #cpp:chain/pickaxe1 run function <a href="#cpp/functions/chain/pickaxe1/damage">cpp:chain/pickaxe1/damage</a>
execute if score #damage cppValue &lt; #max_durality cppValue positioned ~ ~-1 ~ if block ~ ~ ~ #cpp:chain/pickaxe1 run function <a href="#cpp/functions/chain/pickaxe1/damage">cpp:chain/pickaxe1/damage</a>
execute if score #damage cppValue &lt; #max_durality cppValue positioned ~ ~ ~1 if block ~ ~ ~ #cpp:chain/pickaxe1 run function <a href="#cpp/functions/chain/pickaxe1/damage">cpp:chain/pickaxe1/damage</a>
execute if score #damage cppValue &lt; #max_durality cppValue positioned ~ ~ ~-1 if block ~ ~ ~ #cpp:chain/pickaxe1 run function <a href="#cpp/functions/chain/pickaxe1/damage">cpp:chain/pickaxe1/damage</a>
</pre>
<pre class="file" id="cpp/tags/blocks/pickaxe1">cpp/tags/blocks/pickaxe1.json</pre>
<pre>
{
  "replace": false,
  "values": [
    "#cpp:chain/pickaxe",
    "minecraft:copper_ore",
    "minecraft:iron_ore",
    "minecraft:lapis_ore",
    {"id":"#forge:ores/copper","required":false}
  ]
}
</pre>
<pre class="file" id="cpp/functions/chain/pickaxe1/damage">cpp:chain/pickaxe1/damage</pre>
<pre>
<span class="comment"># 挖矿经验</span>
execute as @s[predicate=!cpp:mainhand/silk_touch] run function <a href="#cpp/functions/chain/xp">cpp:chain/xp</a>
function <a href="#cpp/functions/chain/mine">cpp:chain/mine</a>
execute if predicate <a href="#cpp/predicates/damage">cpp:damage</a> run scoreboard players add #damage cppValue 1
scoreboard players add #mined cppValue 1
execute if score #mined cppValue &lt; $maxChainBlocks cppConfig if score #damage cppValue &lt; #max_durality cppValue run function <a href="#cpp/functions/chain/pickaxe1/mark">cpp:chain/pickaxe1/mark</a>
</pre>
<pre class="file" id="cpp/functions/chain/xp">cpp:chain/xp</pre>
<pre>
execute if block ~ ~ ~ #coal_ores run xp add @s 1
execute if block ~ ~ ~ #redstone_ores run xp add @s 3
execute if block ~ ~ ~ nether_quartz_ore run xp add @s 3
execute if block ~ ~ ~ #lapis_ores run xp add @s 4
execute if block ~ ~ ~ #diamond_ores run xp add @s 5
execute if block ~ ~ ~ #emerald_ores run xp add @s 5
</pre>
<pre class="file" id="cpp/functions/chain/mine">cpp:chain/mine</pre>
<pre>
loot spawn ~ ~ ~ mine ~ ~ ~ mainhand
tp @e[type=item,distance=..1] @s
setblock ~ ~ ~ air
</pre>
<pre class="file" id="cpp/item_modifiers/chain_tool">cpp/item_modifiers/chain_tool.json</pre>
<pre>
{
  "function": "minecraft:copy_nbt",
  "source": {
    "type": "storage",
    "source": "cpp:_"
  },
  "ops": [
    {
      "op": "replace",
      "source": "Damage",
      "target": "Damage"
    }
  ]
}
</pre>


<h1 id="算法">§11 算法</h1>

<h2 id="随机数">§11.1 随机数</h2>
<h2 id="不定长均匀分布">§11.1.1 不定长均匀分布</h2>
<p>我们使用战利品的 <code>set_attribute</code> 函数可以便捷地得到 <code>0</code> 至 <code>2048</code> 之间的一个随机浮点数。由此可得到下述算法。</p>

<pre class="file" id="cpp/loot_tables/misc/random">cpp/loot_tables/misc/random.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:tnt",
          "functions": [
            {
              "function": "minecraft:set_attributes",
              "modifiers": [
                {
                  "slot": "mainhand",
                  "name": "1",
                  "attribute": "generic.luck",
                  "operation": "addition",
                  "amount": {
                    "type": "minecraft:uniform",
                    "min": 0,
                    "max": 2048
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}
</pre>

<pre class="file" id="cpp/functions/misc/random">cpp:misc/random</pre>
<pre>
setblock ~ 255 ~ chest
loot insert ~ 255 ~ loot cpp:misc/random
execute store result score #rand cppValue run data get block ~ 255 ~ Items[0].tag.AttributeModifiers[0].Amount 1048575
setblock ~ 255 ~ air
scoreboard players operation #random_interval cppValue = #random_max cppValue
scoreboard players operation #random_interval cppValue -= #random_min cppValue
scoreboard players add #random_interval cppValue 1
scoreboard players operation #rand cppValue %= #random_interval cppValue
scoreboard players operation #rand cppValue += #random_min cppValue
</pre>

<p>先设置 <code>#random_min</code> 和 <code>#random_max</code> 的 <code>cppValue</code> 为随机数的上下界，然后执行该函数，则 <code>#rand</code> 的 <code>cppValue</code> 即为该区间的一个随机数。</p>

<p>另一种做法更为简单，生成一个标记体并将其 <code>UUID[0]</code> 作为随机数来源即可。</p>
<pre class="file" id="cpp/functions/random">cpp:random</pre>
<pre>
summon marker ~ 0 ~ {Tags:["cpp_random"]}
execute store result score #rand cppValue run data get entity @e[tag=cpp_random,limit=1,type=marker] UUID[0]
kill @e[tag=cpp_random,type=marker]
scoreboard players operation #random_interval cppValue = #random_max cppValue
scoreboard players operation #random_interval cppValue -= #random_min cppValue
scoreboard players add #random_interval cppValue 1
scoreboard players operation #rand cppValue %= #random_interval cppValue
scoreboard players operation #rand cppValue += #random_min cppValue
</pre>

<p>对于1.17，我们可以直接将记分板分数作为战利品表的数值使用。</p>
<pre class="file" id="cpp/loot_tables/random">cpp/loot_tables/loot_tablesrandom</pre>
<pre>{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:tnt",
          "functions": [
            {
              "function": "minecraft:set_attributes",
              "modifiers": [
                {
                  "slot": "legs",
                  "name": "1",
                  "attribute": "generic.luck",
                  "operation": "addition",
                  "amount": {
                    "type": "minecraft:uniform",
                    "min": {
                      "type": "minecraft:score",
                      "target": {
                        "type": "minecraft:fixed",
                        "name": "#random_min"
                      },
                      "score": "cppValue"
                    },
                    "max": {
                      "type": "minecraft:score",
                      "target": {
                        "type": "minecraft:fixed",
                        "name": "#random_max"
                      },
                      "score": "cppValue"
                    }
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}
</pre>

<h2 id="定长均匀分布">§11.1.2 定长均匀分布</h2>
<p>对于固定范围的随机数，我们可以直接使用命令<code>random</code>得到。</p>
<pre>
execute store result score #rand value run random 1..100
</pre>

<h2 id="非均匀分布">§11.1.3 非均匀分布</h2>
<p>对于只有若干个值的非均匀分布，我们可以使用战利品表来实现。</p>
<p class="ex">设 2, 3, 5, 7, 11 的概率分别为 0.2, 0.2, 0.36, 0.12, 0.12。</p>
<pre class="file" id="cpp/loot_tables/misc/rand_prime">cpp/loot_tables/misc/rand_prime.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:stone",
          "weight": 20,
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": 2
            }
          ]
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:stone",
          "weight": 20,
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": 3
            }
          ]
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:stone",
          "weight": 36,
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": 5
            }
          ]
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:stone",
          "weight": 12,
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": 7
            }
          ]
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:stone",
          "weight": 12,
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": 11
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<pre class="file" id="cpp/functions/misc/rand_prime">cpp:misc/rand_prime</pre>
<pre>
setblock ~ 255 ~ chest
loot insert ~ 255 ~ loot cpp:misc/rand_prime
execute store result score #rand cppValue run data get block ~ 255 ~ Items[0].Count
setblock ~ 255 ~ air
</pre>

<p class="ex">设 1, 2, 3 的概率分别为 0.35, 0.35, 0.3。</p>
<pre class="file" id="cpp/predicates/misc/rand_30">cpp/predicates/misc/rand_30.json</pre>
<pre>
{
  "condition": "random_chance",
  "chance": 0.3
}
</pre>
<pre class="file" id="cpp/predicates/misc/rand_50">cpp/predicates/misc/rand_50.json</pre>
<pre>
{
  "condition": "random_chance",
  "chance": 0.5
}
</pre>
<pre class="file" id="cpp/functions/misc/rand_123">cpp:misc/rand_123</pre>
<pre>
scoreboard players set #rand cppValue 1
execute if predicate <a href="#cpp/predicates/misc/rand_50">cpp:misc/rand_50</a> run scoreboard players set #rand cppValue 2
execute if predicate <a href="#cpp/predicates/misc/rand_30">cpp:misc/rand_30</a> run scoreboard players set #rand cppValue 3
</pre>

<h2 id="二项分布和泊松分布">§11.1.4 二项分布</h2>
<pre class="file" id="cpp/loot_tables/misc/binomial">cpp/loot_tables/misc/binomial.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:stone",
          "functions": [
            {
              "function": "minecraft:set_attributes",
              "modifiers": [
                {
                  "slot": "mainhand",
                  "name": "random_luck",
                  "attribute": "generic.luck",
                  "operation": "addition",
                  "amount": {
                    "type": "minecraft:binomial"
                    "n": 100,
                    "p": 0.3
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}
</pre>

<pre class="file" id="cpp/functions/misc/binomial">cpp:misc/binomial</pre>
<pre>
setblock ~ 255 ~ chest
loot insert ~ 255 ~ loot cpp:misc/binomial
execute store result score #rand cppValue run data get block ~ 255 ~ Items[0].tag.AttributeModifiers[0].Amount
setblock ~ 255 ~ air
</pre>




<h2 id="世界生成结构">§11.2 世界生成结构</h2>
<p>在<a href="#维度和维度类型">维度和维度类型</a>中，我们介绍了如何通过数据包修改原有维度和添加新的维度。如果想要添加更多的生物群系和各式各样的结构，也可以通过<a href="#自定义世界生成">自定义世界生成</a>来实现。本节我们来介绍添加结构的几种方法。</p>

<h3 id="自定义地物">§11.2.1 自定义地物</h3>
<p>通过自定义<a href="#地物">地物</a>，我们可以添加形状和生成类似树、花、矿石、紫晶洞等、而方块和尺寸有差异的小型结构。</p>

<p>我们在原版的一个生物群系文件基础上做修改来创建一个新的生物群系，并将它添加到我们自定义的维度中。</p>

<pre class="file" id="cpp/worldgen/biome/test">cpp/worldgen/biome/test.json</pre>
<pre>
{
  "effects": {
    "mood_sound": {
      "sound": "minecraft:ambient.cave",
      "tick_delay": 6000,
      "block_search_extent": 8,
      "offset": 2.0
    },
    "sky_color": 7972607,
    "fog_color": 12638463,
    "water_color": 4159204,
    "water_fog_color": 329011
    },
    "surface_builder": "minecraft:grass",
    "carvers": {
      "air": [
        "minecraft:cave",
        "minecraft:canyon"
      ]
    },
    "features": [
      [],
      [
        "minecraft:lake_water",
        "minecraft:lake_lava"
      ],
      [],
      [
        "minecraft:monster_room"
      ],
      [],
      [],
      [
        "minecraft:ore_dirt",
        "minecraft:ore_gravel",
        "minecraft:ore_granite",
        "minecraft:ore_diorite",
        "minecraft:ore_andesite",
        "minecraft:ore_coal",
        "minecraft:ore_iron",
        "minecraft:ore_gold",
        "minecraft:ore_redstone",
        "minecraft:ore_diamond",
        "minecraft:ore_lapis",
        "minecraft:disk_sand",
        "minecraft:disk_clay",
        "minecraft:disk_gravel"
      ],
      [],
      [
        "cpp:small_bush",
        "minecraft:patch_grass_badlands",
        "minecraft:brown_mushroom_normal",
        "minecraft:red_mushroom_normal",
        "minecraft:patch_sugar_cane",
        "minecraft:patch_pumpkin",
        "minecraft:spring_water",
        "minecraft:spring_lava"
      ],
      [
        "minecraft:freeze_top_layer"
      ]
    ],
    "starts": [
      "minecraft:mineshaft",
      "minecraft:stronghold",
      "minecraft:ruined_portal"
    ],
    "spawners": {
    "monster": [
      {
        "type": "minecraft:spider",
        "weight": 100,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:zombie",
        "weight": 95,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:zombie_villager",
        "weight": 5,
        "minCount": 1,
        "maxCount": 1
      },
      {
        "type": "minecraft:skeleton",
        "weight": 100,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:creeper",
        "weight": 100,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:slime",
        "weight": 100,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:enderman",
        "weight": 10,
        "minCount": 1,
        "maxCount": 4
      },
      {
        "type": "minecraft:witch",
        "weight": 5,
        "minCount": 1,
        "maxCount": 1
      }
    ],
    "creature": [
      {
        "type": "minecraft:sheep",
        "weight": 12,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:pig",
        "weight": 10,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:chicken",
        "weight": 10,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:cow",
        "weight": 8,
        "minCount": 4,
        "maxCount": 4
      },
      {
        "type": "minecraft:rabbit",
        "weight": 4,
        "minCount": 2,
        "maxCount": 3
      }
    ],
    "ambient": [
      {
        "type": "minecraft:bat",
        "weight": 10,
        "minCount": 8,
        "maxCount": 8
      }
    ],
    "water_creature": [],
    "water_ambient": [],
    "misc": []
  },
  "spawn_costs": {},
  "player_spawn_friendly": false,
  "precipitation": "rain",
  "temperature": 0.7,
  "downfall": 0.8,
  "category": "forest",
  "depth": 0.1,
  "scale": 0.4
}</pre>
<p>然后创建一个地物文件，里面指定了一个灌木丛。将它添加到生物群系的特征列表中类型为 <code>VEGETAL_DECORATION</code> 的项。</p>
<pre class="file" id="cpp/worldgen/configured_feature/small_bush">cpp/worldgen/configured_feature/small_bush.json</pre>
<pre>
{
  "config": {
    "max_water_depth": 0,
    "ignore_vines": true,
    "heightmap": "OCEAN_FLOOR",
    "minimum_size": {
      "limit": 1,
      "lower_size": 0,
      "upper_size": 1,
      "type": "minecraft:two_layers_feature_size"
    },
    "decorators": [],
    "trunk_provider": {
      "state": {
        "Properties": {
          "axis": "y"
        },
        "Name": "minecraft:oak_log"
      },
      "type": "minecraft:simple_state_provider"
    },
    "leaves_provider": {
      "state": {
        "Properties": {
          "persistent": "false",
          "distance": "7"
        },
        "Name": "minecraft:oak_leaves"
      },
      "type": "minecraft:simple_state_provider"
    },
    "foliage_placer": {
      "radius": 2,
      "offset": 0,
      "height": 3,
      "type": "minecraft:pine_foliage_placer"
    },
    "trunk_placer": {
      "base_height": 1,
      "height_rand_a": 0,
      "height_rand_b": 0,
      "type": "minecraft:straight_trunk_placer"
    }
  },
  "type": "minecraft:tree"
}</pre>
<p>注意由于 <code>small_bush</code> 的 <code>"type":"minecraft:tree"</code>，因此它会生成在原有的树的位置。想要二者均可生成，请使用随机选择的地物。</p>

<h3 id="任意纯方块结构">§11.2.2 任意纯方块结构</h3>
<p>利用结构地物和模板池，我们可以实现自定义的结构的自然生成。可自定义的结构的<a href="#结构地物">结构地物</a>可选的类型有堡垒遗迹、掠夺者前哨站或村庄。注意这样生成的会被视为相应结构(可用于完成进度和 <code>locate</code> 命令)。掠夺者前哨站附近会生成灾厄村民，堡垒遗迹会触发原版进度“光辉岁月”，因此村庄是最合适的，堡垒遗迹次之。注意村庄类型的结构从地表的一层方块起生成，因此为了避免结构陷下去应当将结构的最底一层设置为空，而堡垒遗迹类型的结构生成在地下而非地表。通过使用拼图方块、或直接修改<a href="#结构">结构</a>文件将方块放置在结构外，无论是村庄还是堡垒遗迹我们都可以使结构任意部分生成在地表、任意部分生成在地下。</p>
<p class="ex">添加结构文件 <code>cpp/structures/tp_overworld.nbt</code>，然后利用类型的结构地物来自定义模板池。</p>
<pre class="file" id="cpp/worldgen/configured_structure_feature/totem_pillar">cpp/worldgen/configured_structure_feature/totem_pillar.json</pre>
<pre>
{
  "config": {
    "start_pool": "cpp:totem_pillar",
    "size": 1
  },
  "type": "minecraft:pillager_outpost"
}</pre>
<pre class="file" id="cpp/worldgen/template_pool/totem_pillar">cpp/worldgen/template_pool/totem_pillar.json</pre>
<pre>
{
  "name": "cpp:tp_overworld",
  "fallback": "minecraft:empty",
  "elements": [
    {
      "weight": 1,
      "element": {
      "location": "cpp:tp_overworld",
      "processors": {
        "processors": []
      },
      "projection": "rigid",
      "element_type": "minecraft:legacy_single_pool_element"
      }
    }
  ]
}</pre>
<p>注意这样生成的结构几率非常低，因为原版村庄几率很低，我们可以修改该维度中村庄的生成几率。为了避免在原版可生成村庄的生物群系大量生成村庄，我们可以将其结构设为村庄和自定义结构均有权重的模板池。</p>

<h3 id="含实体结构">§11.2.3 含实体结构</h3>
<p>上一节生成的结构中带上实体标记，然后在函数中检测该标记并执行任意命令并清除标记。</p>


<h3 id="区块标记法">§11.2.4 区块标记法</h3>
<p class="ex">世界生成时，随机生成结构。判断玩家东南32×32范围内是否有标记，如无，添加相应标记在32整数倍坐标处，然后生成战利品表、分散，通过战利品表掉落物来生成结构。也可以使用方块来标记，例如普通生存下y=0使用屏障替换基岩或超平坦生存y=255处使用air替换void_air来实现，这在某些对实体加载有修改的服务端会很有效。</p>

<pre class="file">cpp:tick</pre>
<pre>
execute as @a at @s unless block ~ 0 ~ bedrock run function <a href="#cpp/functions/generate/check">cpp:generate/check</a>
</pre>
<pre class="file" id="cpp/functions/generate/check">cpp:generate/check</pre>
<pre>
execute positioned ~-64 -1 ~-64 unless entity @e[type=marker,tag=cpp_chunk,dx=32,dy=2,dz=32] run function <a href="#cpp/functions/generate/mark">cpp:generate/mark</a>
execute positioned ~-64 -1 ~-32 unless entity @e[type=marker,tag=cpp_chunk,dx=32,dy=2,dz=32] run function <a href="#cpp/functions/generate/mark">cpp:generate/mark</a>
execute positioned ~-64 -1 ~ unless entity @e[type=marker,tag=cpp_chunk,dx=32,dy=2,dz=32] run function <a href="#cpp/functions/generate/mark">cpp:generate/mark</a>
execute positioned ~-32 -1 ~-64 unless entity @e[type=marker,tag=cpp_chunk,dx=32,dy=2,dz=32] run function <a href="#cpp/functions/generate/mark">cpp:generate/mark</a>
execute positioned ~-32 -1 ~-32 unless entity @e[type=marker,tag=cpp_chunk,dx=32,dy=2,dz=32] run function <a href="#cpp/functions/generate/mark">cpp:generate/mark</a>
execute positioned ~-32 -1 ~ unless entity @e[type=marker,tag=cpp_chunk,dx=32,dy=2,dz=32] run function <a href="#cpp/functions/generate/mark">cpp:generate/mark</a>
execute positioned ~ -1 ~-64 unless entity @e[type=marker,tag=cpp_chunk,dx=32,dy=2,dz=32] run function <a href="#cpp/functions/generate/mark">cpp:generate/mark</a>
execute positioned ~ -1 ~-32 unless entity @e[type=marker,tag=cpp_chunk,dx=32,dy=2,dz=32] run function <a href="#cpp/functions/generate/mark">cpp:generate/mark</a>
execute positioned ~ -1 ~ unless entity @e[type=marker,tag=cpp_chunk,dx=32,dy=2,dz=32] run function <a href="#cpp/functions/generate/mark">cpp:generate/mark</a>
</pre>
<pre class="file" id="cpp/functions/generate/mark">cpp:generate/mark</pre>
<pre>
summon marker ~32 0 ~32 {Tags:["cpp_aec_marker","cpp_chunk","cpp_temp"]}
execute as @e[type=marker,tag=cpp_temp] run function <a href="#cpp/functions/generate/aec">cpp:generate/aec</a>
loot spawn ~ ~ ~ loot cpp:misc/generate
execute store result score #t cppValue run spreadplayers ~ ~ 0 15 false @e[type=item,nbt={Item:{tag:{cpp_generate_marker:1b}}}]
execute as @e[type=item,nbt={Item:{tag:{cpp_generate_marker:1b}}}] at @s if block ~ ~-1 ~ #cpp:replacable run tp ~ ~-1 ~
execute as @e[type=item,nbt={Item:{tag:{cpp_generate_marker:1b}}}] at @s if block ~ ~-1 ~ #cpp:replacable run tp ~ ~-1 ~
execute as @e[type=item,nbt={Item:{tag:{cpp_generate_marker:1b}}}] at @s run function <a href="#cpp/functions/generate/build">cpp:generate/build</a>
</pre>
<pre class="file" id="cpp/functions/generate/aec">cpp:generate/aec</pre>
<pre>
execute store result entity @s Pos[0] double 32 run data get entity @s Pos[0] 0.03125
execute store result entity @s Pos[2] double 32 run data get entity @s Pos[2] 0.03125
tag @s remove cpp_temp
</pre>
<pre class="file" id="cpp/functions/generate/build">cpp:generate/build</pre>
<pre>
<span class="comment"># 附魔室</span>
execute as @s[nbt={Item:{tag:{cpp_generate_type:"enchanting_room"}}}] if score #t cppValue matches 1.. run function <a href="#cpp/functions/generate/structures/enchanting_room">cpp:generate/structures/enchanting_room</a>
<span class="comment"># 图腾柱</span>
execute as @s[nbt={Item:{tag:{cpp_generate_type:"tp_overworld"}}}] run function <a href="#cpp/functions/generate/structures/tp_overworld">cpp:generate/structures/tp_overworld</a>
execute as @s[nbt={Item:{tag:{cpp_generate_type:"tp_the_nether"}}}] run function <a href="#cpp/functions/generate/structures/tp_the_nether">cpp:generate/structures/tp_the_nether</a>
execute as @s[nbt={Item:{tag:{cpp_generate_type:"tp_flower"}}}] run function <a href="#cpp/functions/generate/structures/tp_flower">cpp:generate/structures/tp_flower</a>
<span class="comment"># 树</span>
execute as @s[nbt={Item:{tag:{cpp_generate_type:"fruit_tree"}}}] if block ~ ~-1 ~ #cpp:sapling_plantable_on align xyz positioned ~0.5 ~ ~0.5 run function <a href="#cpp/functions/plants/trees/fruit0">cpp:plants/trees/fruit0</a>
execute as @s[nbt={Item:{tag:{cpp_generate_type:"ore_tree"}}}] if block ~ ~-1 ~ #cpp:sapling_plantable_on align xyz positioned ~0.5 ~ ~0.5 run function <a href="#cpp/functions/plants/trees/ore0">cpp:plants/trees/ore0</a>
execute as @s[nbt={Item:{tag:{cpp_generate_type:"wool_tree"}}}] if block ~ ~-1 ~ #cpp:sapling_plantable_on align xyz positioned ~0.5 ~ ~0.5 run function <a href="#cpp/functions/plants/trees/wool0">cpp:plants/trees/wool0</a>
execute as @s[nbt={Item:{tag:{cpp_generate_type:"sakura_tree"}}}] if block ~ ~-1 ~ #cpp:sapling_plantable_on align xyz positioned ~0.5 ~ ~0.5 run function <a href="#cpp/functions/plants/trees/sakura0">cpp:plants/trees/sakura0</a>
<span class="comment"># 农作物</span>
execute as @s[nbt={Item:{tag:{cpp_generate_type:"crops"}}}] if block ~ ~-1 ~ minecraft:grass_block run function <a href="#cpp/functions/generate/structures/crops">cpp:generate/structures/crops</a>
<span class="comment"># 花草</span>
execute as @s[nbt={Item:{tag:{cpp_generate_type:"modcrops"}}}] run function <a href="#cpp/functions/generate/structures/modcrops">cpp:generate/structures/modcrops</a>
kill @s
</pre>
<pre class="file" id="cpp/functions/generate/structures/enchanting_room">cpp:generate/structures/enchanting_room</pre>
<pre>
setblock ~ ~20 ~ structure_block{posX:-1,posY:-20,posZ:-1,name:"cpp:build/enchanting_room",mode:"LOAD"}
setblock ~ ~21 ~ redstone_block
fill ~ ~20 ~ ~ ~21 ~ air

loot insert ~1 ~5 ~ loot cpp:chests/enchanting_room
loot insert ~2 ~5 ~ loot cpp:chests/enchanting_room
loot insert ~3 ~5 ~ loot cpp:chests/enchanting_room
loot insert ~ ~5 ~1 loot cpp:chests/enchanting_room
loot insert ~ ~5 ~2 loot cpp:chests/enchanting_room
loot insert ~ ~5 ~3 loot cpp:chests/enchanting_room
loot insert ~1 ~5 ~4 loot cpp:chests/enchanting_room
loot insert ~2 ~5 ~4 loot cpp:chests/enchanting_room
loot insert ~3 ~5 ~4 loot cpp:chests/enchanting_room
loot insert ~4 ~5 ~1 loot cpp:chests/enchanting_room
loot insert ~4 ~5 ~2 loot cpp:chests/enchanting_room
loot insert ~4 ~5 ~3 loot cpp:chests/enchanting_room
</pre>
<pre class="file" id="cpp/loot_tables/misc/generate">cpp/loot_tables/misc/generate.json</pre>
<pre>
{
  "pools": [
    {
      "rolls": 1,
      "conditions":[
        {
          "condition": "minecraft:random_chance",
          "chance": 0.006
        },
        {
          "condition": "minecraft:location_check",
          "predicate": {
            "dimension": "minecraft:overworld"
          }
        }
      ],
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cpp_generate_marker:1b,cpp_clear:1b,CustomModelData:12970000,cpp_generate_type:'enchanting_room'}"
            }
          ]
        }
      ]
    },
    {
      "rolls": 1,
      "conditions":[
        {
          "condition": "minecraft:random_chance",
          "chance": 0.006
        },
        {
          "condition": "minecraft:location_check",
          "predicate": {
            "dimension": "minecraft:overworld"
          }
        }
      ],
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cpp_generate_marker:1b,cpp_clear:1b,CustomModelData:12970000,cpp_generate_type:'tp_overworld'}"
            }
          ]
        }
      ]
    },
    {
      "rolls": 1,
      "conditions":[
        {
          "condition": "minecraft:random_chance",
          "chance": 0.006
        },
        {
          "condition": "minecraft:location_check",
          "predicate": {
            "dimension": "minecraft:the_nether"
          }
        }
      ],
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cpp_generate_marker:1b,cpp_clear:1b,CustomModelData:12970000,cpp_generate_type:'tp_the_nether'}"
            }
          ]
        }
      ]
    },
    {
      "rolls": 1,
      "conditions":[
        {
          "condition": "minecraft:random_chance",
          "chance": 0.006
        },
        {
          "condition": "minecraft:location_check",
          "predicate": {
            "dimension": "cpp:flower"
          }
        }
      ],
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cpp_generate_marker:1b,cpp_clear:1b,CustomModelData:12970000,cpp_generate_type:'tp_flower'}"
            }
          ]
        }
      ]
    },
    {
      "rolls": 1,
      "conditions":[
        {
          "condition": "minecraft:random_chance",
          "chance": 0.09
        },
        {
          "condition": "minecraft:alternative",
          "terms": [
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "dimension": "minecraft:overworld"
              }
            },
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "dimension": "cpp:flower"
              }
            }            
          ]
        }
      ],
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cpp_generate_marker:1b,cpp_clear:1b,CustomModelData:12970000,cpp_generate_type:'fruit_tree'}"
            }
          ]
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cpp_generate_marker:1b,cpp_clear:1b,CustomModelData:12970000,cpp_generate_type:'ore_tree'}"
            }
          ]
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cpp_generate_marker:1b,cpp_clear:1b,CustomModelData:12970000,cpp_generate_type:'wool_tree'}"
            }
          ]
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cpp_generate_marker:1b,cpp_clear:1b,CustomModelData:12970000,cpp_generate_type:'sakura_tree'}"
            }
          ]
        }
      ]
    },
    {
      "rolls": 1,
      "conditions":[
        {
          "condition": "minecraft:random_chance",
          "chance": 0.15
        },
        {
          "condition": "minecraft:alternative",
          "terms": [
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "biome": "minecraft:desert"
              }
            },
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "biome": "minecraft:desert_hills"
              }
            },
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "biome": "minecraft:desert_lakes"
              }
            },
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "biome": "minecraft:badlands"
              }
            },
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "biome": "minecraft:badlands_plateau"
              }
            },
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "biome": "minecraft:modified_badlands_plateau"
              }
            },
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "biome": "minecraft:wooded_badlands_plateau"
              }
            },
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "biome": "minecraft:modified_wooded_badlands_plateau"
              }
            },
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "biome": "minecraft:eroded_badlands"
              }
            }
          ]
        }
      ],
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cpp_generate_marker:1b,cpp_clear:1b,CustomModelData:12970000,cpp_generate_type:'dead_coral_fan'}"
            },
            {
              "function": "minecraft:set_count",
              "count": {
                "type": "minecraft:uniform",
                "min": 1,
                "max": 5
              }
            }
          ]
        }
      ]
    },
    {
      "rolls": 1,
      "conditions":[
        {
          "condition": "minecraft:random_chance",
          "chance": 0.1
        },
        {
          "condition": "minecraft:alternative",
          "terms": [
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "dimension": "minecraft:overworld"
              }
            },
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "dimension": "cpp:flower"
              }
            }            
          ]
        }
      ],
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cpp_generate_marker:1b,cpp_clear:1b,CustomModelData:12970000,cpp_generate_type:'small_bush'}"
            }
          ]
        }
      ]
    },
    {
      "rolls": 1,
      "conditions":[
        {
          "condition": "minecraft:random_chance",
          "chance": 0.08
        },
        {
          "condition": "minecraft:alternative",
          "terms": [
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "biome": "minecraft:taiga"
              }
            },
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "biome": "minecraft:taiga_hills"
              }
            },
            {
              "condition": "minecraft:location_check",
              "predicate": {
                "biome": "minecraft:taiga_mountains"
              }
            }
          ]
        }
      ],
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cpp_generate_marker:1b,cpp_clear:1b,CustomModelData:12970000,cpp_generate_type:'dead_spruce'}"
            },
            {
              "function": "minecraft:set_count",
              "count": {
                "type": "minecraft:uniform",
                "min": 1,
                "max": 4
              }
            }
          ]
        }
      ]
    },
    {
      "rolls": 1,
      "conditions":[
        {
          "condition": "minecraft:random_chance",
          "chance": 0.04
        },
        {
          "condition": "minecraft:location_check",
          "predicate": {
            "dimension": "minecraft:overworld"
          }
        }
      ],
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cpp_generate_marker:1b,cpp_clear:1b,CustomModelData:12970000,cpp_generate_type:'crops'}"
            },
            {
              "function": "minecraft:set_count",
              "count": {
                "type": "minecraft:uniform",
                "min": 1,
                "max": 4
              }
            }
          ]
        }
      ]
    },
    {
      "rolls": 1,
      "conditions":[
        {
          "condition": "minecraft:random_chance",
          "chance": 0.5
        },
        {
          "condition": "minecraft:location_check",
          "predicate": {
            "dimension": "cpp:flower"
          }
        }
      ],
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:firework_star",
          "functions": [
            {
              "function": "minecraft:set_nbt",
              "tag": "{cpp_generate_marker:1b,cpp_clear:1b,CustomModelData:12970000,cpp_generate_type:'modcrops'}"
            }
          ]
        }
      ]
    }
  ]
}
</pre>
<p>注意在扩散标记物时，当下方为草等方块时，需要将其向下移动以避免结构悬空生成。</p>
<p>我们可以将所有维度的结构标记物均放置在同一战利品表内。</p>
<p>另一种生成为全局替换，例如将主世界的地牢刷怪笼一部分替换为苦力怕刷怪笼，那么在每次检测时，使用 <code>fill</code> 命令强制替换即可。但是该命令开销很大，会导致较大的卡顿。</p>

<h2 id="维度探测">§11.3 维度探测</h2>
<p>由于我们不能预先知道会有哪些维度，因此我们需要在每个维度放置标记来存储该维度的位置，然后记录维度ID。这些操作均需要玩家来主动探测，因此我们使用维度旅行进度来探测新维度。</p>

<p>我们将维度标记存储在区块 <code>(1000000,1000000)</code> 并常加载该区块。</p>

<pre class="file" id="cpp/functions/load">cpp:load</pre>
<pre>
advancement grant @a only cpp:misc/new_dim
</pre>
<pre class="file" id="cpp/advancements/new_dim">cpp/advancements/new_dim.json</pre>
<pre>
{
  "criteria": {
    "entered_dim": {
      "trigger": "minecraft:changed_dimension"
    }
  },
  "rewards": {
    "function": "cpp:adv/new_dim"
  }
}
</pre>
<pre class="file" id="cpp/functions/adv/new_dim">cpp:adv/new_dim</pre>
<pre>
advancement revoke @s only cpp:new_dim
execute positioned 16000000 0 16000000 unless entity @e[type=marker,tag=cpp_dim_marker,distance=..1] run function cpp:init/dim_marker
</pre>
<pre class="file" id="cpp/functions/init/dim_marker">cpp:init/dim_marker</pre>
<pre>
forceload add ~ ~
scoreboard players add #dim_number cppValue 1
summon marker ~ ~ ~ {Tags:["cpp_dim_marker"]}
data modify storage cpp:_ dim append from entity @s Dimension
</pre>
<pre class="file" id="cpp/functions/tick">cpp:tick</pre>
<pre>
execute as @e[type=marker,tag=cpp_dim_marker] unless score @s cppValue matches -2147483648..2147483647 run scoreboard players operation @s cppValue = #dim_number cppValue
</pre>

<p>使用时，我们递归探测玩家所在的维度在列表 <code>cpp:_ dim</code> 中的序号。</p>
<pre class="file" id="cpp/functions/get_dim">cpp:dim_get</pre>
<pre>
scoreboard players set #t cppValue 0
data modify storage cpp:_ dim1 set from storage cpp:_ dim
execute as @p run function cpp:dim_loop
execute as @e[type=marker,tag=cpp_dim_marker] if score @s cppValue = #t cppValue at @s run spreadplayers 0 0 1 10 false @p
</pre>
<pre class="file" id="cpp/functions/dim_loop">cpp:dim_loop</pre>
<pre>
scoreboard players add #t cppValue 1
execute store result score #s cppValue run data modify storage cpp:_ dim1[0] set from entity @s Dimension
data remove storage cpp:_ dim1[0]
execute if score #s cppValue matches 1 if data storage cpp:_ dim1[] run function cpp:dim_loop
</pre>


<h2 id="绘制图案">§11.4 绘制图案</h2>
TBD

<h2 id="循环和递归">§11.5 循环和递归</h2>
TBD

<h2 id="字符操作">§11.6 字符操作</h2>
TBD

<h2 id="位运算与种子">§11.7 位运算与种子</h2>
TBD

</article>
</div>
</body></html>